Imported Upstream version 0.7.2
[platform/upstream/ltrace.git] / sysdeps / linux-gnu / ppc / fetch.c
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 }