fetch.c revision 95792af484c635071ed96107d34a3762c4ca2ef2
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	target_address_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	ctx->stack_pointer
163		= (target_address_t)align((uint64_t)ctx->stack_pointer, a);
164
165	if (valuep != NULL) {
166		valuep->where = VAL_LOC_INFERIOR;
167		valuep->u.address = ctx->stack_pointer + off;
168	}
169
170	ctx->stack_pointer += sz;
171
172	return 0;
173}
174
175static uint64_t
176read_gpr(struct fetch_context *ctx, struct Process *proc, int reg_num)
177{
178	if (proc->e_machine == EM_PPC)
179		return ctx->regs.r32[reg_num];
180	else
181		return ctx->regs.r64[reg_num];
182}
183
184static void snip_small_int(unsigned char *buf, size_t w, size_t sz);
185
186static int
187allocate_gpr(struct fetch_context *ctx, struct Process *proc,
188	     struct arg_type_info *info, struct value *valuep)
189{
190	if (ctx->greg > 10)
191		return allocate_stack_slot(ctx, proc, info, valuep);
192
193	int reg_num = ctx->greg++;
194	if (valuep == NULL)
195		return 0;
196
197	size_t sz = type_sizeof(proc, info);
198	if (sz == (size_t)-1)
199		return -1;
200	assert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
201	if (value_reserve(valuep, sz) == NULL)
202		return -1;
203
204	union {
205		uint64_t i64;
206		unsigned char buf[0];
207	} u;
208
209	u.i64 = read_gpr(ctx, proc, reg_num);
210	if (proc->e_machine == EM_PPC)
211		snip_small_int(u.buf, 8, sz);
212	memcpy(value_get_raw_data(valuep), u.buf, sz);
213	return 0;
214}
215
216static int
217allocate_float(struct fetch_context *ctx, struct Process *proc,
218	       struct arg_type_info *info, struct value *valuep)
219{
220	int pool = proc->e_machine == EM_PPC64 ? 13 : 8;
221	if (ctx->freg <= pool) {
222		union {
223			double d;
224			float f;
225			char buf[0];
226		} u = { .d = ctx->fpregs.fpregs[ctx->freg] };
227
228		ctx->freg++;
229		allocate_gpr(ctx, proc, info, NULL);
230
231		size_t sz = sizeof(double);
232		if (info->type == ARGTYPE_FLOAT) {
233			sz = sizeof(float);
234			u.f = (float)u.d;
235		}
236
237		if (value_reserve(valuep, sz) == NULL)
238			return -1;
239
240		memcpy(value_get_raw_data(valuep), u.buf, sz);
241		return 0;
242	}
243	return allocate_stack_slot(ctx, proc, info, valuep);
244}
245
246/* The support for little endian PowerPC is in upstream Linux and BFD,
247 * and Unix-like Solaris, which we might well support at some point,
248 * runs PowerPC in little endian as well.  This code moves SZ-sized
249 * value to the beginning of W-sized BUF regardless of
250 * endian.  */
251static void
252snip_small_int(unsigned char *buf, size_t w, size_t sz)
253{
254	assert(w == 4 || w == 8);
255	union {
256		uint64_t i64;
257		uint32_t i32;
258		uint16_t i16;
259		uint8_t i8;
260		char buf[0];
261	} u;
262	memcpy(u.buf, buf, w);
263	if (w == 4)
264		u.i64 = u.i32;
265
266	switch (sz) {
267	case 1:
268		u.i8 = u.i64;
269		break;
270	case 2:
271		u.i16 = u.i64;
272		break;
273	case 4:
274		u.i32 = u.i64;
275	case 8:
276		break;
277	}
278
279	memcpy(buf, u.buf, sz);
280}
281
282static int
283allocate_argument(struct fetch_context *ctx, struct Process *proc,
284		  struct arg_type_info *info, struct value *valuep)
285{
286	/* Floating point types and void are handled specially.  */
287	switch (info->type) {
288	case ARGTYPE_VOID:
289		value_set_word(valuep, 0);
290		return 0;
291
292	case ARGTYPE_FLOAT:
293	case ARGTYPE_DOUBLE:
294		return allocate_float(ctx, proc, info, valuep);
295
296	case ARGTYPE_STRUCT:
297		if (proc->e_machine == EM_PPC) {
298			if (value_pass_by_reference(valuep) < 0)
299				return -1;
300		} else {
301			/* PPC64: Fixed size aggregates and unions passed by
302			 * value are mapped to as many doublewords of the
303			 * parameter save area as the value uses in memory.
304			 * [...] The first eight doublewords mapped to the
305			 * parameter save area correspond to the registers r3
306			 * through r10.  */
307		}
308		/* fall through */
309	case ARGTYPE_CHAR:
310	case ARGTYPE_SHORT:
311	case ARGTYPE_USHORT:
312	case ARGTYPE_INT:
313	case ARGTYPE_UINT:
314	case ARGTYPE_LONG:
315	case ARGTYPE_ULONG:
316	case ARGTYPE_POINTER:
317		break;
318
319	case ARGTYPE_ARRAY:
320		/* Arrays decay into pointers.  XXX Fortran?  */
321		assert(info->type != ARGTYPE_ARRAY);
322		abort();
323	}
324
325	unsigned width = proc->e_machine == EM_PPC64 ? 8 : 4;
326
327	/* For other cases (integral types and aggregates), read the
328	 * eightbytes comprising the data.  */
329	size_t sz = type_sizeof(proc, valuep->type);
330	if (sz == (size_t)-1)
331		return -1;
332	size_t slots = (sz + width - 1) / width;  /* Round up.  */
333	unsigned char *buf = value_reserve(valuep, slots * width);
334	if (buf == NULL)
335		return -1;
336	struct arg_type_info *long_info = type_get_simple(ARGTYPE_LONG);
337
338	unsigned char *ptr = buf;
339	while (slots-- > 0) {
340		struct value val;
341		value_init(&val, proc, NULL, long_info, 0);
342		int rc = allocate_gpr(ctx, proc, long_info, &val);
343		if (rc >= 0) {
344			memcpy(ptr, value_get_data(&val, NULL), width);
345			ptr += width;
346		}
347		value_destroy(&val);
348		if (rc < 0)
349			return rc;
350	}
351
352	/* Small values need post-processing.  */
353	if (sz < width) {
354		switch (info->type) {
355		case ARGTYPE_LONG:
356		case ARGTYPE_ULONG:
357		case ARGTYPE_POINTER:
358		case ARGTYPE_DOUBLE:
359		case ARGTYPE_VOID:
360			abort();
361
362		/* Simple integer types (char, short, int, long, enum)
363		 * are mapped to a single doubleword. Values shorter
364		 * than a doubleword are sign or zero extended as
365		 * necessary.  */
366		case ARGTYPE_CHAR:
367		case ARGTYPE_SHORT:
368		case ARGTYPE_INT:
369		case ARGTYPE_USHORT:
370		case ARGTYPE_UINT:
371			snip_small_int(buf, width, sz);
372			break;
373
374		/* Single precision floating point values are mapped
375		 * to the second word in a single doubleword.
376		 *
377		 * An aggregate or union smaller than one doubleword
378		 * in size is padded so that it appears in the least
379		 * significant bits of the doubleword.  */
380		case ARGTYPE_FLOAT:
381		case ARGTYPE_ARRAY:
382		case ARGTYPE_STRUCT:
383			memmove(buf, buf + width - sz, sz);
384			break;
385		}
386	}
387
388	return 0;
389}
390
391int
392arch_fetch_arg_next(struct fetch_context *ctx, enum tof type,
393		    struct Process *proc,
394		    struct arg_type_info *info, struct value *valuep)
395{
396	return allocate_argument(ctx, proc, info, valuep);
397}
398
399int
400arch_fetch_retval(struct fetch_context *ctx, enum tof type,
401		  struct Process *proc, struct arg_type_info *info,
402		  struct value *valuep)
403{
404	if (ctx->ret_struct) {
405		assert(info->type == ARGTYPE_STRUCT);
406
407		uint64_t addr = read_gpr(ctx, proc, 3);
408		value_init(valuep, proc, NULL, info, 0);
409
410		valuep->where = VAL_LOC_INFERIOR;
411		valuep->u.address = (target_address_t)addr;
412		return 0;
413	}
414
415	if (fetch_context_init(proc, ctx) < 0)
416		return -1;
417	return allocate_argument(ctx, proc, info, valuep);
418}
419
420void
421arch_fetch_arg_done(struct fetch_context *context)
422{
423	free(context);
424}
425