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
fetch_context_init(struct process * proc,struct fetch_context * context)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 *
arch_fetch_arg_init(enum tof type,struct process * proc,struct arg_type_info * ret_info)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 *
arch_fetch_arg_clone(struct process * proc,struct fetch_context * 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
allocate_stack_slot(struct fetch_context * ctx,struct process * proc,struct arg_type_info * info,struct value * valuep)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
read_gpr(struct fetch_context * ctx,struct process * proc,int reg_num)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
align_small_int(unsigned char * buf,size_t w,size_t sz)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
allocate_gpr(struct fetch_context * ctx,struct process * proc,struct arg_type_info * info,struct value * valuep)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
allocate_float(struct fetch_context * ctx,struct process * proc,struct arg_type_info * info,struct value * valuep)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
allocate_argument(struct fetch_context * ctx,struct process * proc,struct arg_type_info * info,struct value * valuep)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
arch_fetch_arg_next(struct fetch_context * ctx,enum tof type,struct process * proc,struct arg_type_info * info,struct value * valuep)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
arch_fetch_retval(struct fetch_context * ctx,enum tof type,struct process * proc,struct arg_type_info * info,struct value * 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)
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
arch_fetch_arg_done(struct fetch_context * context)433 arch_fetch_arg_done(struct fetch_context *context)
434 {
435 free(context);
436 }
437