fetch.c revision 5b5c256d0e9076e745908a43acc46353265a5608
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 <asm/ptrace.h>
22#include <sys/ptrace.h>
23#include <sys/ucontext.h>
24#include <assert.h>
25#include <errno.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29
30#include "backend.h"
31#include "fetch.h"
32#include "type.h"
33#include "proc.h"
34#include "value.h"
35
36struct fetch_context {
37	struct user_regs_struct regs;
38	arch_addr_t stack_pointer;
39	int greg;
40	int freg;
41};
42
43static int
44s390x(struct fetch_context *ctx)
45{
46	/* +--------+--------+--------+
47	 * | PSW.31 | PSW.32 | mode   |
48	 * +--------+--------+--------+
49	 * | 0      | 0      | 24-bit | Not supported in Linux
50	 * | 0      | 1      | 31-bit | s390 compatible mode
51	 * | 1      | 1      | 64-bit | z/Architecture, "s390x"
52	 * +--------+--------+--------+
53	 * (Note: The leftmost bit is PSW.0, rightmost PSW.63.)
54	 */
55
56#ifdef __s390x__
57	if ((ctx->regs.psw.mask & 0x180000000UL) == 0x180000000UL)
58		return 1;
59#endif
60	return 0;
61}
62
63static int
64fetch_register_banks(struct Process *proc, struct fetch_context *ctx)
65{
66	ptrace_area parea;
67	parea.len = sizeof(ctx->regs);
68	parea.process_addr = (uintptr_t)&ctx->regs;
69	parea.kernel_addr = 0;
70	if (ptrace(PTRACE_PEEKUSR_AREA, proc->pid, &parea, NULL) < 0) {
71		fprintf(stderr, "fetch_register_banks GPR: %s\n",
72			strerror(errno));
73		return -1;
74	}
75	return 0;
76}
77
78static int
79fetch_context_init(struct Process *proc, struct fetch_context *context)
80{
81	context->greg = 2;
82	context->freg = 0;
83	return fetch_register_banks(proc, context);
84}
85
86struct fetch_context *
87arch_fetch_arg_init(enum tof type, struct Process *proc,
88		    struct arg_type_info *ret_info)
89{
90	struct fetch_context *context = malloc(sizeof(*context));
91	if (context == NULL
92	    || fetch_context_init(proc, context) < 0) {
93		fprintf(stderr, "arch_fetch_arg_init: %s\n",
94			strerror(errno));
95		free(context);
96		return NULL;
97	}
98
99	context->stack_pointer = get_stack_pointer(proc)
100		+ (s390x(context) ? 160 : 96);
101	if (ret_info->type == ARGTYPE_STRUCT)
102		++context->greg;
103
104	return context;
105}
106
107struct fetch_context *
108arch_fetch_arg_clone(struct Process *proc,
109		     struct fetch_context *context)
110{
111	struct fetch_context *clone = malloc(sizeof(*context));
112	if (clone == NULL)
113		return NULL;
114	*clone = *context;
115	return clone;
116}
117
118static int
119allocate_stack_slot(struct fetch_context *ctx, struct Process *proc,
120		    struct arg_type_info *info, struct value *valuep,
121		    size_t sz)
122{
123	/* Note: here we shouldn't see large composite types, those
124	 * are passed by reference, which is handled below.  Here we
125	 * only deal with integers, floats, small structs, etc.  */
126
127	size_t a;
128	if (s390x(ctx)) {
129		assert(sz <= 8);
130		a = 8;
131	} else {
132		/* Note: double is 8 bytes.  */
133		assert(sz <= 8);
134		a = 4;
135	}
136
137	size_t off = sz < a ? a - sz : 0;
138
139	valuep->where = VAL_LOC_INFERIOR;
140	valuep->u.address = ctx->stack_pointer + off;
141
142	ctx->stack_pointer += sz > a ? sz : a;
143	return 0;
144}
145
146static void
147copy_gpr(struct fetch_context *ctx, struct value *valuep, int regno)
148{
149	value_set_word(valuep, ctx->regs.gprs[regno]);
150}
151
152static int
153allocate_gpr(struct fetch_context *ctx, struct Process *proc,
154	     struct arg_type_info *info, struct value *valuep,
155	     size_t sz)
156{
157	if (ctx->greg > 6)
158		return allocate_stack_slot(ctx, proc, info, valuep, sz);
159
160	copy_gpr(ctx, valuep, ctx->greg++);
161	return 0;
162}
163
164static int
165allocate_gpr_pair(struct fetch_context *ctx, struct Process *proc,
166		  struct arg_type_info *info, struct value *valuep,
167		  size_t sz)
168{
169	assert(!s390x(ctx));
170	assert(sz <= 8);
171
172	if (ctx->greg > 5) {
173		ctx->greg = 7;
174		return allocate_stack_slot(ctx, proc, info, valuep, sz);
175	}
176
177	if (value_reserve(valuep, sz) == NULL)
178		return -1;
179
180	unsigned char *ptr = value_get_raw_data(valuep);
181	union {
182		struct {
183			uint32_t a;
184			uint32_t b;
185		};
186		unsigned char buf[8];
187	} u;
188	u.a = ctx->regs.gprs[ctx->greg++];
189	u.b = ctx->regs.gprs[ctx->greg++];
190	memcpy(ptr, u.buf, sz);
191
192	return 0;
193}
194
195static int
196allocate_fpr(struct fetch_context *ctx, struct Process *proc,
197	     struct arg_type_info *info, struct value *valuep,
198	     size_t sz)
199{
200	int pool = s390x(ctx) ? 6 : 2;
201
202	if (ctx->freg > pool)
203		return allocate_stack_slot(ctx, proc, info, valuep, sz);
204
205	if (value_reserve(valuep, sz) == NULL)
206		return -1;
207
208	memcpy(value_get_raw_data(valuep),
209	       &ctx->regs.fp_regs.fprs[ctx->freg], sz);
210	ctx->freg += 2;
211
212	return 0;
213}
214
215int
216arch_fetch_arg_next(struct fetch_context *ctx, enum tof type,
217		    struct Process *proc,
218		    struct arg_type_info *info, struct value *valuep)
219{
220	size_t sz = type_sizeof(proc, info);
221	if (sz == (size_t)-1)
222		return -1;
223
224	switch (info->type) {
225	case ARGTYPE_VOID:
226		value_set_word(valuep, 0);
227		return 0;
228
229	case ARGTYPE_STRUCT:
230		if (type_get_fp_equivalent(info) != NULL)
231			/* fall through */
232	case ARGTYPE_FLOAT:
233	case ARGTYPE_DOUBLE:
234			return allocate_fpr(ctx, proc, info, valuep, sz);
235
236		/* Structures<4 bytes on s390 and structures<8 bytes
237		 * on s390x are passed in register.  On s390, long
238		 * long and structures<8 bytes are passed in two
239		 * consecutive registers (if two are available).  */
240
241		if (sz <= (s390x(ctx) ? 8 : 4))
242			return allocate_gpr(ctx, proc, info, valuep, sz);
243		else if (sz <= 8)
244			return allocate_gpr_pair(ctx, proc, info, valuep, sz);
245
246		/* fall through */
247
248	case ARGTYPE_ARRAY:
249		if (value_pass_by_reference(valuep) < 0)
250			return -1;
251		/* fall through */
252
253	case ARGTYPE_INT:
254	case ARGTYPE_UINT:
255	case ARGTYPE_LONG:
256	case ARGTYPE_ULONG:
257	case ARGTYPE_CHAR:
258	case ARGTYPE_SHORT:
259	case ARGTYPE_USHORT:
260	case ARGTYPE_POINTER:
261		return allocate_gpr(ctx, proc, info, valuep, sz);
262
263	default:
264		assert(info->type != info->type);
265		abort();
266	}
267	return -1;
268}
269
270int
271arch_fetch_retval(struct fetch_context *ctx, enum tof type,
272		  struct Process *proc, struct arg_type_info *info,
273		  struct value *valuep)
274{
275	if (info->type == ARGTYPE_STRUCT) {
276		if (value_pass_by_reference(valuep) < 0)
277			return -1;
278		copy_gpr(ctx, valuep, 2);
279		return 0;
280	}
281
282	if (fetch_context_init(proc, ctx) < 0)
283		return -1;
284	return arch_fetch_arg_next(ctx, type, proc, info, valuep);
285}
286
287void
288arch_fetch_arg_done(struct fetch_context *context)
289{
290	free(context);
291}
292