Home | History | Annotate | Download | only in ppc
      1 /*
      2  * This file is part of ltrace.
      3  * Copyright (C) 2012 Petr Machata, Red Hat Inc.
      4  *
      5  * This program is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU General Public License as
      7  * published by the Free Software Foundation; either version 2 of the
      8  * License, or (at your option) any later version.
      9  *
     10  * This program is distributed in the hope that it will be useful, but
     11  * WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  * General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this program; if not, write to the Free Software
     17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
     18  * 02110-1301 USA
     19  */
     20 
     21 #include <assert.h>
     22 #include <stdint.h>
     23 #include <stdlib.h>
     24 #include <string.h>
     25 #include <sys/ucontext.h>
     26 
     27 #include "backend.h"
     28 #include "fetch.h"
     29 #include "type.h"
     30 #include "ptrace.h"
     31 #include "proc.h"
     32 #include "value.h"
     33 
     34 static int allocate_gpr(struct fetch_context *ctx, struct process *proc,
     35 			struct arg_type_info *info, struct value *valuep);
     36 
     37 /* Floating point registers have the same width on 32-bit as well as
     38  * 64-bit PPC, but <ucontext.h> presents a different API depending on
     39  * whether ltrace is PPC32 or PPC64.
     40  *
     41  * This is PPC64 definition.  The PPC32 is simply an array of 33
     42  * doubles, and doesn't contain the terminating pad.  Both seem
     43  * compatible enough.  */
     44 struct fpregs_t
     45 {
     46 	double fpregs[32];
     47 	double fpscr;
     48 	unsigned int _pad[2];
     49 };
     50 
     51 typedef uint32_t gregs32_t[48];
     52 typedef uint64_t gregs64_t[48];
     53 
     54 struct fetch_context {
     55 	arch_addr_t stack_pointer;
     56 	int greg;
     57 	int freg;
     58 	int ret_struct;
     59 
     60 	union {
     61 		gregs32_t r32;
     62 		gregs64_t r64;
     63 	} regs;
     64 	struct fpregs_t fpregs;
     65 
     66 };
     67 
     68 static int
     69 fetch_context_init(struct process *proc, struct fetch_context *context)
     70 {
     71 	context->greg = 3;
     72 	context->freg = 1;
     73 
     74 	if (proc->e_machine == EM_PPC)
     75 		context->stack_pointer = proc->stack_pointer + 8;
     76 	else
     77 		context->stack_pointer = proc->stack_pointer + 112;
     78 
     79 	/* When ltrace is 64-bit, we might use PTRACE_GETREGS to
     80 	 * obtain 64-bit as well as 32-bit registers.  But if we do it
     81 	 * this way, 32-bit ltrace can obtain 64-bit registers.
     82 	 *
     83 	 * XXX this direction is not supported as of this writing, but
     84 	 * should be eventually.  */
     85 	if (proc->e_machine == EM_PPC64) {
     86 		if (ptrace(PTRACE_GETREGS64, proc->pid, 0,
     87 			   &context->regs.r64) < 0)
     88 			return -1;
     89 	} else {
     90 #ifdef __powerpc64__
     91 		if (ptrace(PTRACE_GETREGS, proc->pid, 0,
     92 			  &context->regs.r64) < 0)
     93 			return -1;
     94 		unsigned i;
     95 		for (i = 0; i < sizeof(context->regs.r64)/8; ++i)
     96 			context->regs.r32[i] = context->regs.r64[i];
     97 #else
     98 		if (ptrace(PTRACE_GETREGS, proc->pid, 0,
     99 			  &context->regs.r32) < 0)
    100 			return -1;
    101 #endif
    102 	}
    103 
    104 	if (ptrace(PTRACE_GETFPREGS, proc->pid, 0, &context->fpregs) < 0)
    105 		return -1;
    106 
    107 	return 0;
    108 }
    109 
    110 struct fetch_context *
    111 arch_fetch_arg_init(enum tof type, struct process *proc,
    112 		    struct arg_type_info *ret_info)
    113 {
    114 	struct fetch_context *context = malloc(sizeof(*context));
    115 	if (context == NULL
    116 	    || fetch_context_init(proc, context) < 0) {
    117 		free(context);
    118 		return NULL;
    119 	}
    120 
    121 	/* Aggregates or unions of any length, and character strings
    122 	 * of length longer than 8 bytes, will be returned in a
    123 	 * storage buffer allocated by the caller. The caller will
    124 	 * pass the address of this buffer as a hidden first argument
    125 	 * in r3, causing the first explicit argument to be passed in
    126 	 * r4.  */
    127 	context->ret_struct = ret_info->type == ARGTYPE_STRUCT;
    128 	if (context->ret_struct)
    129 		context->greg++;
    130 
    131 	return context;
    132 }
    133 
    134 struct fetch_context *
    135 arch_fetch_arg_clone(struct process *proc,
    136 		     struct fetch_context *context)
    137 {
    138 	struct fetch_context *clone = malloc(sizeof(*context));
    139 	if (clone == NULL)
    140 		return NULL;
    141 	*clone = *context;
    142 	return clone;
    143 }
    144 
    145 static int
    146 allocate_stack_slot(struct fetch_context *ctx, struct process *proc,
    147 		    struct arg_type_info *info, struct value *valuep)
    148 {
    149 	size_t sz = type_sizeof(proc, info);
    150 	if (sz == (size_t)-1)
    151 		return -1;
    152 
    153 	size_t a = type_alignof(proc, info);
    154 	size_t off = 0;
    155 	if (proc->e_machine == EM_PPC && a < 4)
    156 		a = 4;
    157 	else if (proc->e_machine == EM_PPC64 && a < 8)
    158 		a = 8;
    159 
    160 	/* XXX Remove the two double casts when arch_addr_t
    161 	 * becomes integral type.  */
    162 	uintptr_t tmp = align((uint64_t)(uintptr_t)ctx->stack_pointer, a);
    163 	ctx->stack_pointer = (arch_addr_t)tmp;
    164 
    165 	if (valuep != NULL)
    166 		value_in_inferior(valuep, ctx->stack_pointer + off);
    167 	ctx->stack_pointer += sz;
    168 
    169 	return 0;
    170 }
    171 
    172 static uint64_t
    173 read_gpr(struct fetch_context *ctx, struct process *proc, int reg_num)
    174 {
    175 	if (proc->e_machine == EM_PPC)
    176 		return ctx->regs.r32[reg_num];
    177 	else
    178 		return ctx->regs.r64[reg_num];
    179 }
    180 
    181 /* The support for little endian PowerPC is in upstream Linux and BFD,
    182  * and Unix-like Solaris, which we might well support at some point,
    183  * runs PowerPC in little endian as well.  This code moves SZ-sized
    184  * value to the beginning of W-sized BUF regardless of
    185  * endian.  */
    186 static void
    187 align_small_int(unsigned char *buf, size_t w, size_t sz)
    188 {
    189 	assert(w == 4 || w == 8);
    190 	union {
    191 		uint64_t i64;
    192 		uint32_t i32;
    193 		uint16_t i16;
    194 		uint8_t i8;
    195 		char buf[0];
    196 	} u;
    197 	memcpy(u.buf, buf, w);
    198 	if (w == 4)
    199 		u.i64 = u.i32;
    200 
    201 	switch (sz) {
    202 	case 1:
    203 		u.i8 = u.i64;
    204 		break;
    205 	case 2:
    206 		u.i16 = u.i64;
    207 		break;
    208 	case 4:
    209 		u.i32 = u.i64;
    210 	case 8:
    211 		break;
    212 	}
    213 
    214 	memcpy(buf, u.buf, sz);
    215 }
    216 
    217 static int
    218 allocate_gpr(struct fetch_context *ctx, struct process *proc,
    219 	     struct arg_type_info *info, struct value *valuep)
    220 {
    221 	if (ctx->greg > 10)
    222 		return allocate_stack_slot(ctx, proc, info, valuep);
    223 
    224 	int reg_num = ctx->greg++;
    225 	if (valuep == NULL)
    226 		return 0;
    227 
    228 	size_t sz = type_sizeof(proc, info);
    229 	if (sz == (size_t)-1)
    230 		return -1;
    231 	assert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
    232 	if (value_reserve(valuep, sz) == NULL)
    233 		return -1;
    234 
    235 	union {
    236 		uint64_t i64;
    237 		unsigned char buf[0];
    238 	} u;
    239 
    240 	u.i64 = read_gpr(ctx, proc, reg_num);
    241 	if (proc->e_machine == EM_PPC)
    242 		align_small_int(u.buf, 8, sz);
    243 	memcpy(value_get_raw_data(valuep), u.buf, sz);
    244 	return 0;
    245 }
    246 
    247 static int
    248 allocate_float(struct fetch_context *ctx, struct process *proc,
    249 	       struct arg_type_info *info, struct value *valuep)
    250 {
    251 	int pool = proc->e_machine == EM_PPC64 ? 13 : 8;
    252 	if (ctx->freg <= pool) {
    253 		union {
    254 			double d;
    255 			float f;
    256 			char buf[0];
    257 		} u = { .d = ctx->fpregs.fpregs[ctx->freg] };
    258 
    259 		ctx->freg++;
    260 		if (proc->e_machine == EM_PPC64)
    261 			allocate_gpr(ctx, proc, info, NULL);
    262 
    263 		size_t sz = sizeof(double);
    264 		if (info->type == ARGTYPE_FLOAT) {
    265 			sz = sizeof(float);
    266 			u.f = (float)u.d;
    267 		}
    268 
    269 		if (value_reserve(valuep, sz) == NULL)
    270 			return -1;
    271 
    272 		memcpy(value_get_raw_data(valuep), u.buf, sz);
    273 		return 0;
    274 	}
    275 	return allocate_stack_slot(ctx, proc, info, valuep);
    276 }
    277 
    278 static int
    279 allocate_argument(struct fetch_context *ctx, struct process *proc,
    280 		  struct arg_type_info *info, struct value *valuep)
    281 {
    282 	/* Floating point types and void are handled specially.  */
    283 	switch (info->type) {
    284 	case ARGTYPE_VOID:
    285 		value_set_word(valuep, 0);
    286 		return 0;
    287 
    288 	case ARGTYPE_FLOAT:
    289 	case ARGTYPE_DOUBLE:
    290 		return allocate_float(ctx, proc, info, valuep);
    291 
    292 	case ARGTYPE_STRUCT:
    293 		if (proc->e_machine == EM_PPC) {
    294 			if (value_pass_by_reference(valuep) < 0)
    295 				return -1;
    296 		} else {
    297 			/* PPC64: Fixed size aggregates and unions passed by
    298 			 * value are mapped to as many doublewords of the
    299 			 * parameter save area as the value uses in memory.
    300 			 * [...] The first eight doublewords mapped to the
    301 			 * parameter save area correspond to the registers r3
    302 			 * through r10.  */
    303 		}
    304 		/* fall through */
    305 	case ARGTYPE_CHAR:
    306 	case ARGTYPE_SHORT:
    307 	case ARGTYPE_USHORT:
    308 	case ARGTYPE_INT:
    309 	case ARGTYPE_UINT:
    310 	case ARGTYPE_LONG:
    311 	case ARGTYPE_ULONG:
    312 	case ARGTYPE_POINTER:
    313 		break;
    314 
    315 	case ARGTYPE_ARRAY:
    316 		/* Arrays decay into pointers.  XXX Fortran?  */
    317 	default:
    318 		assert(info->type != info->type);
    319 		abort();
    320 	}
    321 
    322 	unsigned width = proc->e_machine == EM_PPC64 ? 8 : 4;
    323 
    324 	/* For other cases (integral types and aggregates), read the
    325 	 * eightbytes comprising the data.  */
    326 	size_t sz = type_sizeof(proc, valuep->type);
    327 	if (sz == (size_t)-1)
    328 		return -1;
    329 	size_t slots = (sz + width - 1) / width;  /* Round up.  */
    330 	unsigned char *buf = value_reserve(valuep, slots * width);
    331 	if (buf == NULL)
    332 		return -1;
    333 	struct arg_type_info *long_info = type_get_simple(ARGTYPE_LONG);
    334 
    335 	unsigned char *ptr = buf;
    336 	while (slots-- > 0) {
    337 		struct value val;
    338 		value_init(&val, proc, NULL, long_info, 0);
    339 
    340 		/* Floating point registers [...] are used [...] to
    341 		   pass [...] one member aggregates passed by value
    342 		   containing a floating point value[.]  Note that for
    343 		   one member aggregates, "containing" extends to
    344 		   aggregates within aggregates ad infinitum.  */
    345 		int rc;
    346 		struct arg_type_info *fp_info
    347 			= type_get_fp_equivalent(valuep->type);
    348 		if (fp_info != NULL)
    349 			rc = allocate_float(ctx, proc, fp_info, &val);
    350 		else
    351 			rc = allocate_gpr(ctx, proc, long_info, &val);
    352 
    353 		if (rc >= 0) {
    354 			memcpy(ptr, value_get_data(&val, NULL), width);
    355 			ptr += width;
    356 		}
    357 		value_destroy(&val);
    358 
    359 		/* Bail out if we failed or if we are dealing with
    360 		 * FP-equivalent.  Those don't need the adjustments
    361 		 * made below.  */
    362 		if (rc < 0 || fp_info != NULL)
    363 			return rc;
    364 	}
    365 
    366 	/* Small values need post-processing.  */
    367 	if (sz < width) {
    368 		switch (info->type) {
    369 		default:
    370 			abort();
    371 
    372 		/* Simple integer types (char, short, int, long, enum)
    373 		 * are mapped to a single doubleword. Values shorter
    374 		 * than a doubleword are sign or zero extended as
    375 		 * necessary.  */
    376 		case ARGTYPE_CHAR:
    377 		case ARGTYPE_SHORT:
    378 		case ARGTYPE_INT:
    379 		case ARGTYPE_USHORT:
    380 		case ARGTYPE_UINT:
    381 			align_small_int(buf, width, sz);
    382 			break;
    383 
    384 		/* Single precision floating point values are mapped
    385 		 * to the second word in a single doubleword.
    386 		 *
    387 		 * An aggregate or union smaller than one doubleword
    388 		 * in size is padded so that it appears in the least
    389 		 * significant bits of the doubleword.  */
    390 		case ARGTYPE_FLOAT:
    391 		case ARGTYPE_ARRAY:
    392 		case ARGTYPE_STRUCT:
    393 			memmove(buf, buf + width - sz, sz);
    394 			break;
    395 		}
    396 	}
    397 
    398 	return 0;
    399 }
    400 
    401 int
    402 arch_fetch_arg_next(struct fetch_context *ctx, enum tof type,
    403 		    struct process *proc,
    404 		    struct arg_type_info *info, struct value *valuep)
    405 {
    406 	return allocate_argument(ctx, proc, info, valuep);
    407 }
    408 
    409 int
    410 arch_fetch_retval(struct fetch_context *ctx, enum tof type,
    411 		  struct process *proc, struct arg_type_info *info,
    412 		  struct value *valuep)
    413 {
    414 	if (ctx->ret_struct) {
    415 		assert(info->type == ARGTYPE_STRUCT);
    416 
    417 		uint64_t addr = read_gpr(ctx, proc, 3);
    418 		value_init(valuep, proc, NULL, info, 0);
    419 
    420 		valuep->where = VAL_LOC_INFERIOR;
    421 		/* XXX Remove the double cast when arch_addr_t
    422 		 * becomes integral type. */
    423 		valuep->u.address = (arch_addr_t)(uintptr_t)addr;
    424 		return 0;
    425 	}
    426 
    427 	if (fetch_context_init(proc, ctx) < 0)
    428 		return -1;
    429 	return allocate_argument(ctx, proc, info, valuep);
    430 }
    431 
    432 void
    433 arch_fetch_arg_done(struct fetch_context *context)
    434 {
    435 	free(context);
    436 }
    437