Home | History | Annotate | Download | only in s390
      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 }
    297