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