On s390{,x}, r2 is scrambled after syscall entry
[platform/upstream/ltrace.git] / sysdeps / linux-gnu / s390 / 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 <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
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
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
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 *
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 *
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
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
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
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
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
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
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
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
293 arch_fetch_arg_done(struct fetch_context *context)
294 {
295         free(context);
296 }