fetch.c revision 54737daf1c51ec826fcabc8189a7ff891f29d59b
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 27#include <stdio.h> 28 29#include "backend.h" 30#include "fetch.h" 31#include "type.h" 32#include "proc.h" 33#include "value.h" 34 35static int allocate_gpr(struct fetch_context *ctx, struct Process *proc, 36 struct arg_type_info *info, struct value *valuep); 37 38/* Floating point registers have the same width on 32-bit as well as 39 * 64-bit PPC, but <ucontext.h> presents a different API depending on 40 * whether ltrace is PPC32 or PPC64. 41 * 42 * This is PPC64 definition. The PPC32 is simply an array of 33 43 * doubles, and doesn't contain the terminating pad. Both seem 44 * compatible enough. */ 45struct fpregs_t 46{ 47 double fpregs[32]; 48 double fpscr; 49 unsigned int _pad[2]; 50}; 51 52typedef uint32_t gregs32_t[48]; 53typedef uint64_t gregs64_t[48]; 54 55struct fetch_context { 56 target_address_t stack_pointer; 57 int greg; 58 int freg; 59 int ret_struct; 60 61 union { 62 gregs32_t r32; 63 gregs64_t r64; 64 } regs; 65 struct fpregs_t fpregs; 66 67}; 68 69static int 70fetch_context_init(struct Process *proc, struct fetch_context *context) 71{ 72 context->greg = 3; 73 context->freg = 1; 74 75 if (proc->e_machine == EM_PPC64) 76 context->stack_pointer = proc->stack_pointer + 8; 77 else 78 context->stack_pointer = proc->stack_pointer + 112; 79 80 /* When ltrace is 64-bit, we might use PTRACE_GETREGS to 81 * obtain 64-bit as well as 32-bit registers. But if we do it 82 * this way, 32-bit ltrace can obtain 64-bit registers. 83 * 84 * XXX this direction is not supported as of this writing, but 85 * should be eventually. */ 86 if (proc->e_machine == EM_PPC64) { 87 if (ptrace(PTRACE_GETREGS64, proc->pid, 0, 88 &context->regs.r64) < 0) 89 return -1; 90 } else if (ptrace(PTRACE_GETREGS, proc->pid, 0, 91 &context->regs.r32) < 0) { 92 return -1; 93 } 94 95 if (ptrace(PTRACE_GETFPREGS, proc->pid, 0, &context->fpregs) < 0) 96 return -1; 97 98 return 0; 99} 100 101struct fetch_context * 102arch_fetch_arg_init(enum tof type, struct Process *proc, 103 struct arg_type_info *ret_info) 104{ 105 struct fetch_context *context = malloc(sizeof(*context)); 106 if (context == NULL 107 || fetch_context_init(proc, context) < 0) { 108 free(context); 109 return NULL; 110 } 111 112 /* Aggregates or unions of any length, and character strings 113 * of length longer than 8 bytes, will be returned in a 114 * storage buffer allocated by the caller. The caller will 115 * pass the address of this buffer as a hidden first argument 116 * in r3, causing the first explicit argument to be passed in 117 * r4. */ 118 context->ret_struct = ret_info->type == ARGTYPE_STRUCT; 119 if (context->ret_struct) 120 context->greg++; 121 122 return context; 123} 124 125struct fetch_context * 126arch_fetch_arg_clone(struct Process *proc, 127 struct fetch_context *context) 128{ 129 struct fetch_context *clone = malloc(sizeof(*context)); 130 if (clone == NULL) 131 return NULL; 132 *clone = *context; 133 return clone; 134} 135 136static int 137allocate_stack_slot(struct fetch_context *ctx, struct Process *proc, 138 struct arg_type_info *info, struct value *valuep) 139{ 140 assert(!"allocate_stack_slot not implemented"); 141 abort(); 142} 143 144static int 145allocate_float(struct fetch_context *ctx, struct Process *proc, 146 struct arg_type_info *info, struct value *valuep) 147{ 148 int pool = proc->e_machine == EM_PPC ? 8 : 13; 149 if (ctx->freg <= pool) { 150 union { 151 double d; 152 float f; 153 char buf[0]; 154 } u = { .d = ctx->fpregs.fpregs[ctx->freg] }; 155 156 ctx->freg++; 157 ctx->greg++; 158 159 size_t sz = sizeof(double); 160 if (info->type == ARGTYPE_FLOAT) { 161 sz = sizeof(float); 162 u.f = (float)u.d; 163 } 164 165 if (value_reserve(valuep, sz) == NULL) 166 return -1; 167 168 memcpy(value_get_raw_data(valuep), u.buf, sz); 169 return 0; 170 } 171 return allocate_stack_slot(ctx, proc, info, valuep); 172} 173 174static uint64_t 175read_gpr(struct fetch_context *ctx, struct Process *proc, int reg_num) 176{ 177 if (proc->e_machine == EM_PPC) 178 return ctx->regs.r32[reg_num]; 179 else 180 return ctx->regs.r64[reg_num]; 181} 182 183static int 184allocate_gpr(struct fetch_context *ctx, struct Process *proc, 185 struct arg_type_info *info, struct value *valuep) 186{ 187 if (ctx->greg > 10) 188 return allocate_stack_slot(ctx, proc, info, valuep); 189 190 int reg_num = ctx->greg++; 191 if (valuep == NULL) 192 return 0; 193 194 size_t sz = type_sizeof(proc, info); 195 if (sz == (size_t)-1) 196 return -1; 197 assert(sz == 1 || sz == 2 || sz == 4 || sz == 8); 198 if (value_reserve(valuep, sz) == NULL) 199 return -1; 200 201 union { 202 uint64_t i64; 203 uint32_t i32; 204 uint16_t i16; 205 uint8_t i8; 206 char buf[0]; 207 } u; 208 209 u.i64 = read_gpr(ctx, proc, reg_num); 210 211 /* The support for little endian PowerPC is in upstream Linux 212 * and BFD, and Unix-like Solaris, which we might well support 213 * at some point, runs PowerPC in little endian as well. So 214 * let's do it the hard way. */ 215 switch (sz) { 216 case 1: 217 u.i8 = u.i64; 218 break; 219 case 2: 220 u.i16 = u.i64; 221 break; 222 case 4: 223 u.i32 = u.i64; 224 case 8: 225 break; 226 } 227 228 memcpy(value_get_raw_data(valuep), u.buf, sz); 229 return 0; 230} 231 232static int 233allocate_argument(struct fetch_context *ctx, struct Process *proc, 234 struct arg_type_info *info, struct value *valuep) 235{ 236 switch (info->type) { 237 case ARGTYPE_VOID: 238 value_set_word(valuep, 0); 239 return 0; 240 241 case ARGTYPE_INT: 242 case ARGTYPE_UINT: 243 case ARGTYPE_LONG: 244 case ARGTYPE_ULONG: 245 case ARGTYPE_CHAR: 246 case ARGTYPE_SHORT: 247 case ARGTYPE_USHORT: 248 case ARGTYPE_POINTER: 249 return allocate_gpr(ctx, proc, info, valuep); 250 251 case ARGTYPE_FLOAT: 252 case ARGTYPE_DOUBLE: 253 return allocate_float(ctx, proc, info, valuep); 254 255 case ARGTYPE_STRUCT: 256 /* Fixed size aggregates and unions passed by value 257 * are mapped to as many doublewords of the parameter 258 * save area as the value uses in memory. [...] The 259 * first eight doublewords mapped to the parameter 260 * save area correspond to the registers r3 through 261 * r10. */ 262 assert(!"arch_fetch_arg_next structures not implemented"); 263 abort(); 264 265 case ARGTYPE_ARRAY: 266 /* Arrays decay into pointers. */ 267 assert(info->type != ARGTYPE_ARRAY); 268 abort(); 269 } 270 271 assert(info->type != info->type); 272 abort(); 273} 274 275int 276arch_fetch_arg_next(struct fetch_context *ctx, enum tof type, 277 struct Process *proc, 278 struct arg_type_info *info, struct value *valuep) 279{ 280 return allocate_argument(ctx, proc, info, valuep); 281} 282 283int 284arch_fetch_retval(struct fetch_context *ctx, enum tof type, 285 struct Process *proc, struct arg_type_info *info, 286 struct value *valuep) 287{ 288 if (ctx->ret_struct) { 289 assert(info->type == ARGTYPE_STRUCT); 290 291 uint64_t addr = read_gpr(ctx, proc, 3); 292 value_init(valuep, proc, NULL, info, 0); 293 294 if (value_pass_by_reference(valuep) < 0) { 295 value_destroy(valuep); 296 return -1; 297 } 298 299 valuep->where = VAL_LOC_INFERIOR; 300 valuep->u.address = (target_address_t)addr; 301 return 0; 302 } 303 304 if (fetch_context_init(proc, ctx) < 0) 305 return -1; 306 return allocate_argument(ctx, proc, info, valuep); 307} 308 309void 310arch_fetch_arg_done(struct fetch_context *context) 311{ 312 free(context); 313} 314