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