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