fetch.c revision df59c75ee9fa70343c9af929403cd3d371443714
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 64fp_equivalent(struct arg_type_info *info) 65{ 66 switch (info->type) { 67 case ARGTYPE_VOID: 68 case ARGTYPE_INT: 69 case ARGTYPE_UINT: 70 case ARGTYPE_LONG: 71 case ARGTYPE_ULONG: 72 case ARGTYPE_CHAR: 73 case ARGTYPE_SHORT: 74 case ARGTYPE_USHORT: 75 case ARGTYPE_ARRAY: 76 case ARGTYPE_POINTER: 77 return 0; 78 79 case ARGTYPE_FLOAT: 80 case ARGTYPE_DOUBLE: 81 return 1; 82 83 case ARGTYPE_STRUCT: 84 if (type_struct_size(info) != 1) 85 return 0; 86 return fp_equivalent(type_element(info, 0)); 87 } 88 assert(info->type != info->type); 89 abort(); 90} 91 92static int 93fetch_register_banks(struct Process *proc, struct fetch_context *ctx) 94{ 95 ptrace_area parea; 96 parea.len = sizeof(ctx->regs); 97 parea.process_addr = (uintptr_t)&ctx->regs; 98 parea.kernel_addr = 0; 99 if (ptrace(PTRACE_PEEKUSR_AREA, proc->pid, &parea, NULL) < 0) { 100 fprintf(stderr, "fetch_register_banks GPR: %s\n", 101 strerror(errno)); 102 return -1; 103 } 104 return 0; 105} 106 107static int 108fetch_context_init(struct Process *proc, struct fetch_context *context) 109{ 110 context->greg = 2; 111 context->freg = 0; 112 return fetch_register_banks(proc, context); 113} 114 115struct fetch_context * 116arch_fetch_arg_init(enum tof type, struct Process *proc, 117 struct arg_type_info *ret_info) 118{ 119 struct fetch_context *context = malloc(sizeof(*context)); 120 if (context == NULL 121 || fetch_context_init(proc, context) < 0) { 122 fprintf(stderr, "arch_fetch_arg_init: %s\n", 123 strerror(errno)); 124 free(context); 125 return NULL; 126 } 127 128 context->stack_pointer = get_stack_pointer(proc) 129 + (s390x(context) ? 160 : 96); 130 if (ret_info->type == ARGTYPE_STRUCT) 131 ++context->greg; 132 133 return context; 134} 135 136struct fetch_context * 137arch_fetch_arg_clone(struct Process *proc, 138 struct fetch_context *context) 139{ 140 struct fetch_context *clone = malloc(sizeof(*context)); 141 if (clone == NULL) 142 return NULL; 143 *clone = *context; 144 return clone; 145} 146 147static int 148allocate_stack_slot(struct fetch_context *ctx, struct Process *proc, 149 struct arg_type_info *info, struct value *valuep, 150 size_t sz) 151{ 152 /* Note: here we shouldn't see large composite types, those 153 * are passed by reference, which is handled below. Here we 154 * only deal with integers, floats, small structs, etc. */ 155 156 size_t a; 157 if (s390x(ctx)) { 158 assert(sz <= 8); 159 a = 8; 160 } else { 161 /* Note: double is 8 bytes. */ 162 assert(sz <= 8); 163 a = 4; 164 } 165 166 size_t off = sz < a ? a - sz : 0; 167 168 valuep->where = VAL_LOC_INFERIOR; 169 valuep->u.address = ctx->stack_pointer + off; 170 171 ctx->stack_pointer += sz > a ? sz : a; 172 return 0; 173} 174 175static void 176copy_gpr(struct fetch_context *ctx, struct value *valuep, int regno) 177{ 178 value_set_word(valuep, ctx->regs.gprs[regno]); 179} 180 181static int 182allocate_gpr(struct fetch_context *ctx, struct Process *proc, 183 struct arg_type_info *info, struct value *valuep, 184 size_t sz) 185{ 186 if (ctx->greg > 6) 187 return allocate_stack_slot(ctx, proc, info, valuep, sz); 188 189 copy_gpr(ctx, valuep, ctx->greg++); 190 return 0; 191} 192 193static int 194allocate_gpr_pair(struct fetch_context *ctx, struct Process *proc, 195 struct arg_type_info *info, struct value *valuep, 196 size_t sz) 197{ 198 assert(!s390x(ctx)); 199 assert(sz <= 8); 200 201 if (ctx->greg > 5) { 202 ctx->greg = 7; 203 return allocate_stack_slot(ctx, proc, info, valuep, sz); 204 } 205 206 if (value_reserve(valuep, sz) == NULL) 207 return -1; 208 209 unsigned char *ptr = value_get_raw_data(valuep); 210 union { 211 struct { 212 uint32_t a; 213 uint32_t b; 214 }; 215 unsigned char buf[8]; 216 } u; 217 u.a = ctx->regs.gprs[ctx->greg++]; 218 u.b = ctx->regs.gprs[ctx->greg++]; 219 memcpy(ptr, u.buf, sz); 220 221 return 0; 222} 223 224static int 225allocate_fpr(struct fetch_context *ctx, struct Process *proc, 226 struct arg_type_info *info, struct value *valuep, 227 size_t sz) 228{ 229 int pool = s390x(ctx) ? 6 : 2; 230 231 if (ctx->freg > pool) 232 return allocate_stack_slot(ctx, proc, info, valuep, sz); 233 234 if (value_reserve(valuep, sz) == NULL) 235 return -1; 236 237 memcpy(value_get_raw_data(valuep), 238 &ctx->regs.fp_regs.fprs[ctx->freg], sz); 239 ctx->freg += 2; 240 241 return 0; 242} 243 244int 245arch_fetch_arg_next(struct fetch_context *ctx, enum tof type, 246 struct Process *proc, 247 struct arg_type_info *info, struct value *valuep) 248{ 249 size_t sz = type_sizeof(proc, info); 250 if (sz == (size_t)-1) 251 return -1; 252 253 /* XXX structures<4 bytes on s390 and structures<8 bytes on 254 * s390x are passed in register. On s390, long long and 255 * structures<8 bytes are passed in two consecutive 256 * registers (if two are available). */ 257 258 switch (info->type) { 259 case ARGTYPE_VOID: 260 value_set_word(valuep, 0); 261 return 0; 262 263 case ARGTYPE_STRUCT: 264 if (fp_equivalent(info)) 265 /* fall through */ 266 case ARGTYPE_FLOAT: 267 case ARGTYPE_DOUBLE: 268 return allocate_fpr(ctx, proc, info, valuep, sz); 269 270 /* Small structures are passed in registers. */ 271 if (sz <= (s390x(ctx) ? 8 : 4)) 272 return allocate_gpr(ctx, proc, info, valuep, sz); 273 else if (sz <= 8) 274 return allocate_gpr_pair(ctx, proc, info, valuep, sz); 275 /* fall through */ 276 277 case ARGTYPE_ARRAY: 278 if (value_pass_by_reference(valuep) < 0) 279 return -1; 280 /* fall through */ 281 282 case ARGTYPE_INT: 283 case ARGTYPE_UINT: 284 case ARGTYPE_LONG: 285 case ARGTYPE_ULONG: 286 case ARGTYPE_CHAR: 287 case ARGTYPE_SHORT: 288 case ARGTYPE_USHORT: 289 case ARGTYPE_POINTER: 290 return allocate_gpr(ctx, proc, info, valuep, sz); 291 } 292 return -1; 293} 294 295int 296arch_fetch_retval(struct fetch_context *ctx, enum tof type, 297 struct Process *proc, struct arg_type_info *info, 298 struct value *valuep) 299{ 300 if (info->type == ARGTYPE_STRUCT) { 301 if (value_pass_by_reference(valuep) < 0) 302 return -1; 303 copy_gpr(ctx, valuep, 2); 304 return 0; 305 } 306 307 if (fetch_context_init(proc, ctx) < 0) 308 return -1; 309 return arch_fetch_arg_next(ctx, type, proc, info, valuep); 310} 311 312void 313arch_fetch_arg_done(struct fetch_context *context) 314{ 315 free(context); 316} 317