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