2 * This file is part of ltrace.
3 * Copyright (C) 2012 Petr Machata, Red Hat Inc.
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.
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.
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
25 #include <sys/ucontext.h>
34 static int allocate_gpr(struct fetch_context *ctx, struct Process *proc,
35 struct arg_type_info *info, struct value *valuep);
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.
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. */
51 typedef uint32_t gregs32_t[48];
52 typedef uint64_t gregs64_t[48];
54 struct fetch_context {
55 arch_addr_t stack_pointer;
64 struct fpregs_t fpregs;
69 fetch_context_init(struct Process *proc, struct fetch_context *context)
74 if (proc->e_machine == EM_PPC)
75 context->stack_pointer = proc->stack_pointer + 8;
77 context->stack_pointer = proc->stack_pointer + 112;
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.
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)
91 if (ptrace(PTRACE_GETREGS, proc->pid, 0,
92 &context->regs.r64) < 0)
95 for (i = 0; i < sizeof(context->regs.r64)/8; ++i)
96 context->regs.r32[i] = context->regs.r64[i];
98 if (ptrace(PTRACE_GETREGS, proc->pid, 0,
99 &context->regs.r32) < 0)
104 if (ptrace(PTRACE_GETFPREGS, proc->pid, 0, &context->fpregs) < 0)
110 struct fetch_context *
111 arch_fetch_arg_init(enum tof type, struct Process *proc,
112 struct arg_type_info *ret_info)
114 struct fetch_context *context = malloc(sizeof(*context));
116 || fetch_context_init(proc, context) < 0) {
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
127 context->ret_struct = ret_info->type == ARGTYPE_STRUCT;
128 if (context->ret_struct)
134 struct fetch_context *
135 arch_fetch_arg_clone(struct Process *proc,
136 struct fetch_context *context)
138 struct fetch_context *clone = malloc(sizeof(*context));
146 allocate_stack_slot(struct fetch_context *ctx, struct Process *proc,
147 struct arg_type_info *info, struct value *valuep)
149 size_t sz = type_sizeof(proc, info);
150 if (sz == (size_t)-1)
153 size_t a = type_alignof(proc, info);
155 if (proc->e_machine == EM_PPC && a < 4)
157 else if (proc->e_machine == EM_PPC64 && a < 8)
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;
166 value_in_inferior(valuep, ctx->stack_pointer + off);
167 ctx->stack_pointer += sz;
173 read_gpr(struct fetch_context *ctx, struct Process *proc, int reg_num)
175 if (proc->e_machine == EM_PPC)
176 return ctx->regs.r32[reg_num];
178 return ctx->regs.r64[reg_num];
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
187 align_small_int(unsigned char *buf, size_t w, size_t sz)
189 assert(w == 4 || w == 8);
197 memcpy(u.buf, buf, w);
214 memcpy(buf, u.buf, sz);
218 allocate_gpr(struct fetch_context *ctx, struct Process *proc,
219 struct arg_type_info *info, struct value *valuep)
222 return allocate_stack_slot(ctx, proc, info, valuep);
224 int reg_num = ctx->greg++;
228 size_t sz = type_sizeof(proc, info);
229 if (sz == (size_t)-1)
231 assert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
232 if (value_reserve(valuep, sz) == NULL)
237 unsigned char buf[0];
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);
248 allocate_float(struct fetch_context *ctx, struct Process *proc,
249 struct arg_type_info *info, struct value *valuep)
251 int pool = proc->e_machine == EM_PPC64 ? 13 : 8;
252 if (ctx->freg <= pool) {
257 } u = { .d = ctx->fpregs.fpregs[ctx->freg] };
260 if (proc->e_machine == EM_PPC64)
261 allocate_gpr(ctx, proc, info, NULL);
263 size_t sz = sizeof(double);
264 if (info->type == ARGTYPE_FLOAT) {
269 if (value_reserve(valuep, sz) == NULL)
272 memcpy(value_get_raw_data(valuep), u.buf, sz);
275 return allocate_stack_slot(ctx, proc, info, valuep);
279 allocate_argument(struct fetch_context *ctx, struct Process *proc,
280 struct arg_type_info *info, struct value *valuep)
282 /* Floating point types and void are handled specially. */
283 switch (info->type) {
285 value_set_word(valuep, 0);
290 return allocate_float(ctx, proc, info, valuep);
293 if (proc->e_machine == EM_PPC) {
294 if (value_pass_by_reference(valuep) < 0)
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
312 case ARGTYPE_POINTER:
316 /* Arrays decay into pointers. XXX Fortran? */
318 assert(info->type != info->type);
322 unsigned width = proc->e_machine == EM_PPC64 ? 8 : 4;
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)
329 size_t slots = (sz + width - 1) / width; /* Round up. */
330 unsigned char *buf = value_reserve(valuep, slots * width);
333 struct arg_type_info *long_info = type_get_simple(ARGTYPE_LONG);
335 unsigned char *ptr = buf;
336 while (slots-- > 0) {
338 value_init(&val, proc, NULL, long_info, 0);
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. */
346 struct arg_type_info *fp_info
347 = type_get_fp_equivalent(valuep->type);
349 rc = allocate_float(ctx, proc, fp_info, &val);
351 rc = allocate_gpr(ctx, proc, long_info, &val);
354 memcpy(ptr, value_get_data(&val, NULL), width);
359 /* Bail out if we failed or if we are dealing with
360 * FP-equivalent. Those don't need the adjustments
362 if (rc < 0 || fp_info != NULL)
366 /* Small values need post-processing. */
368 switch (info->type) {
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
381 align_small_int(buf, width, sz);
384 /* Single precision floating point values are mapped
385 * to the second word in a single doubleword.
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. */
393 memmove(buf, buf + width - sz, sz);
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)
406 return allocate_argument(ctx, proc, info, valuep);
410 arch_fetch_retval(struct fetch_context *ctx, enum tof type,
411 struct Process *proc, struct arg_type_info *info,
412 struct value *valuep)
414 if (ctx->ret_struct) {
415 assert(info->type == ARGTYPE_STRUCT);
417 uint64_t addr = read_gpr(ctx, proc, 3);
418 value_init(valuep, proc, NULL, info, 0);
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;
427 if (fetch_context_init(proc, ctx) < 0)
429 return allocate_argument(ctx, proc, info, valuep);
433 arch_fetch_arg_done(struct fetch_context *context)