• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
37 struct fetch_context {
38 	struct user_regs_struct regs;
39 	arch_addr_t stack_pointer;
40 	int greg;
41 	int freg;
42 };
43 
44 static int
s390x(struct fetch_context * ctx)45 s390x(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 
64 static int
fetch_register_banks(struct process * proc,struct fetch_context * ctx,bool syscall_enter)65 fetch_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 
84 static int
fetch_context_init(struct process * proc,struct fetch_context * context,bool syscall_enter)85 fetch_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 
93 struct fetch_context *
arch_fetch_arg_init(enum tof type,struct process * proc,struct arg_type_info * ret_info)94 arch_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 
114 struct fetch_context *
arch_fetch_arg_clone(struct process * proc,struct fetch_context * context)115 arch_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 
125 static int
allocate_stack_slot(struct fetch_context * ctx,struct process * proc,struct arg_type_info * info,struct value * valuep,size_t sz)126 allocate_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 
151 static void
copy_gpr(struct fetch_context * ctx,struct value * valuep,int regno)152 copy_gpr(struct fetch_context *ctx, struct value *valuep, int regno)
153 {
154 	value_set_word(valuep, ctx->regs.gprs[regno]);
155 }
156 
157 static int
allocate_gpr(struct fetch_context * ctx,struct process * proc,struct arg_type_info * info,struct value * valuep,size_t sz)158 allocate_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 
169 static int
allocate_gpr_pair(struct fetch_context * ctx,struct process * proc,struct arg_type_info * info,struct value * valuep,size_t sz)170 allocate_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 
200 static int
allocate_fpr(struct fetch_context * ctx,struct process * proc,struct arg_type_info * info,struct value * valuep,size_t sz)201 allocate_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 
220 int
arch_fetch_arg_next(struct fetch_context * ctx,enum tof type,struct process * proc,struct arg_type_info * info,struct value * valuep)221 arch_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 
275 int
arch_fetch_retval(struct fetch_context * ctx,enum tof type,struct process * proc,struct arg_type_info * info,struct value * valuep)276 arch_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 
292 void
arch_fetch_arg_done(struct fetch_context * context)293 arch_fetch_arg_done(struct fetch_context *context)
294 {
295 	free(context);
296 }
297