fetch.c revision 929bd57ca202fd2f2e8485ebf65d683e664f67b5
1a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata/* 2a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * This file is part of ltrace. 3a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * Copyright (C) 2011,2012 Petr Machata 4a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * 5a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * This program is free software; you can redistribute it and/or 6a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * modify it under the terms of the GNU General Public License as 7a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * published by the Free Software Foundation; either version 2 of the 8a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * License, or (at your option) any later version. 9a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * 10a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * This program is distributed in the hope that it will be useful, but 11a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of 12a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * General Public License for more details. 14a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * 15a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * You should have received a copy of the GNU General Public License 16a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * along with this program; if not, write to the Free Software 17a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 18a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * 02110-1301 USA 19a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata */ 20a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 21a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata#include "config.h" 22a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 23a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata#include <sys/types.h> 24a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata#include <assert.h> 25a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata#include <gelf.h> 26a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata#include <stddef.h> 27a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata#include <stdint.h> 28a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata#include <stdlib.h> 29a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata#include <string.h> 300ffa9f3f82febbcd475318ac282c456adb76c73cPetr Machata#include <stdio.h> 31a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 32ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#include "backend.h" 33a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata#include "expr.h" 34a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata#include "fetch.h" 35a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata#include "proc.h" 36a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata#include "ptrace.h" 37a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata#include "type.h" 38a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata#include "value.h" 39a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 40a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataenum arg_class { 41a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata CLASS_INTEGER, 42a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata CLASS_SSE, 43a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata CLASS_NO, 44a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata CLASS_MEMORY, 45a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata CLASS_X87, 46a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}; 47a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 48a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataenum reg_pool { 49a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata POOL_FUNCALL, 50a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata POOL_SYSCALL, 51a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* A common pool for system call and function call return is 52a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * enough, the ABI is similar enough. */ 53a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata POOL_RETVAL, 54a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}; 55a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 56a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastruct fetch_context 57a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 58a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct user_regs_struct iregs; 59a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct user_fpregs_struct fpregs; 60ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata 61a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata void *stack_pointer; 62a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t ireg; /* Used-up integer registers. */ 63a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t freg; /* Used-up floating registers. */ 64a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 65a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata union { 66a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct { 67a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* Storage classes for return type. We need 68a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * to compute them anyway, so let's keep them 69a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * around. */ 70a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata enum arg_class ret_classes[2]; 71a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata ssize_t num_ret_classes; 72a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } x86_64; 73a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct { 74a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct value retval; 75ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata } ix86; 76a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } u; 77a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}; 78a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 79ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#ifndef __x86_64__ 80ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata__attribute__((noreturn)) static void 81ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machatai386_unreachable(void) 82ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata{ 83ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata abort(); 84ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata} 85ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif 86ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata 87a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic int 88a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatacontains_unaligned_fields(struct arg_type_info *info) 89a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 90a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* XXX currently we don't support structure alignment. */ 91a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return 0; 92a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 93a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 94a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic int 95a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatahas_nontrivial_ctor_dtor(struct arg_type_info *info) 96a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 97a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* XXX another unsupported aspect of type info. We might call 98a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * these types "class" instead of "struct" in the config 99a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * file. */ 100a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return 0; 101a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 102a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 103a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic void 104a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatacopy_int_register(struct fetch_context *context, 105a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct value *valuep, unsigned long val, size_t offset) 106a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 107a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (valuep != NULL) { 108a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata unsigned char *buf = value_get_raw_data(valuep); 109a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata memcpy(buf + offset, &val, sizeof(val)); 110a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 111a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata context->ireg++; 112a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 113a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 114a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic void 115a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatacopy_sse_register(struct fetch_context *context, struct value *valuep, 116a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata int half, size_t sz, size_t offset) 117a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 118ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#ifdef __x86_64__ 119a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata union { 120a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata uint32_t sse[4]; 121a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata long halves[2]; 122a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } u; 123a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t off = 4 * context->freg++; 124a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata memcpy(u.sse, context->fpregs.xmm_space + off, sizeof(u.sse)); 125a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 126a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (valuep != NULL) { 127a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata unsigned char *buf = value_get_raw_data(valuep); 128a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata memcpy(buf + offset, u.halves + half, sz); 129a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 130ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#else 131ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata i386_unreachable(); 132ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif 133a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 134a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 135a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic void 136a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataallocate_stack_slot(struct fetch_context *context, 137a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct value *valuep, size_t sz, size_t offset, 138a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t archw) 139a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 140a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t a = type_alignof(valuep->inferior, valuep->type); 141a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (a < archw) 142a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata a = archw; 143a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata context->stack_pointer 144a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata = (void *)align((unsigned long)context->stack_pointer, a); 145a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 1460ffa9f3f82febbcd475318ac282c456adb76c73cPetr Machata if (valuep != NULL) 1470ffa9f3f82febbcd475318ac282c456adb76c73cPetr Machata value_in_inferior(valuep, context->stack_pointer); 148a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata context->stack_pointer += sz; 149a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 150a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 151a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic enum arg_class 152a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataallocate_x87(struct fetch_context *context, struct value *valuep, 153a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t sz, size_t offset, enum reg_pool pool, size_t archw) 154a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 155a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* Both i386 and x86_64 ABI only ever really use x87 registers 156a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * to return values. Otherwise, the parameter is treated as 157a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * if it were CLASS_MEMORY. On x86_64 x87 registers are only 158a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * used for returning long double values, which we currently 159a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * don't support. */ 160a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 161a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (pool != POOL_RETVAL) { 162a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata allocate_stack_slot(context, valuep, sz, offset, archw); 163a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return CLASS_MEMORY; 164a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 165a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 166a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 167a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* If the class is X87, the value is returned on the X87 stack 168a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * in %st0 as 80-bit x87 number. 169a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * 170a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * If the class is X87UP, the value is returned together with 171a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * the previous X87 value in %st0. 172a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * 173a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * If the class is COMPLEX_X87, the real part of the value is 174a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * returned in %st0 and the imaginary part in %st1. */ 175a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 176a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (valuep != NULL) { 177a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata union { 178a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata long double ld; 179a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata double d; 180a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata float f; 181a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata char buf[0]; 182a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } u; 183a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 184a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* The x87 floating point value is in long double 185a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * format, so we need to convert in to the right type. 186a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * Alternatively we might just leave it as is and 187a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * smuggle the long double type into the value (via 188a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * value_set_type), but for that we first need to 189a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * support long double in the first place. */ 190a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 191ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#ifdef __x86_64__ 192ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata unsigned int *reg; 193ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#else 194ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata long int *reg; 195ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif 196ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata reg = &context->fpregs.st_space[0]; 197a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata memcpy(&u.ld, reg, sizeof(u)); 198a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (valuep->type->type == ARGTYPE_FLOAT) 199a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata u.f = (float)u.ld; 200a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata else if (valuep->type->type == ARGTYPE_DOUBLE) 201a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata u.d = (double)u.ld; 202a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata else 203a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata assert(!"Unexpected floating type!"), abort(); 204a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 205a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata unsigned char *buf = value_get_raw_data(valuep); 206a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata memcpy(buf + offset, u.buf, sz); 207a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 208a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return CLASS_X87; 209a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 210a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 211a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic enum arg_class 212a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataallocate_integer(struct fetch_context *context, struct value *valuep, 213a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t sz, size_t offset, enum reg_pool pool) 214a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 215a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata#define HANDLE(NUM, WHICH) \ 216a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case NUM: \ 217a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata copy_int_register(context, valuep, \ 218a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata context->iregs.WHICH, offset); \ 219a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return CLASS_INTEGER 220a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 221a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata switch (pool) { 222a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case POOL_FUNCALL: 223ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#ifdef __x86_64__ 224a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata switch (context->ireg) { 225a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata HANDLE(0, rdi); 226a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata HANDLE(1, rsi); 227a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata HANDLE(2, rdx); 228a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata HANDLE(3, rcx); 229a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata HANDLE(4, r8); 230a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata HANDLE(5, r9); 231a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata default: 232a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata allocate_stack_slot(context, valuep, sz, offset, 8); 233a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return CLASS_MEMORY; 234a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 235ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#else 236ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata i386_unreachable(); 237ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif 238a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 239a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case POOL_SYSCALL: 240ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#ifdef __x86_64__ 241a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata switch (context->ireg) { 242a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata HANDLE(0, rdi); 243a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata HANDLE(1, rsi); 244a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata HANDLE(2, rdx); 245a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata HANDLE(3, r10); 246a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata HANDLE(4, r8); 247a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata HANDLE(5, r9); 248a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata default: 249a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata assert(!"More than six syscall arguments???"); 250a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata abort(); 251a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 252ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#else 253ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata i386_unreachable(); 254ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif 255a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 256a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case POOL_RETVAL: 257a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata switch (context->ireg) { 258ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#ifdef __x86_64__ 259a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata HANDLE(0, rax); 260a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata HANDLE(1, rdx); 261ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#else 262ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata HANDLE(0, eax); 263ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif 264a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata default: 265ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata assert(!"Too many return value classes."); 266a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata abort(); 267a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 268a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 269a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 270a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata abort(); 271a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 272a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata#undef HANDLE 273a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 274a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 275a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic enum arg_class 276a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataallocate_sse(struct fetch_context *context, struct value *valuep, 277a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t sz, size_t offset, enum reg_pool pool) 278a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 279a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t num_regs = 0; 280a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata switch (pool) { 281a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case POOL_FUNCALL: 282a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata num_regs = 8; 283a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case POOL_SYSCALL: 284a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata break; 285a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case POOL_RETVAL: 286a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata num_regs = 2; 287a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 288a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 289a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (context->freg >= num_regs) { 290a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* We shouldn't see overflow for RETVAL or SYSCALL 291a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * pool. */ 292a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata assert(pool == POOL_FUNCALL); 293a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata allocate_stack_slot(context, valuep, sz, offset, 8); 294a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return CLASS_MEMORY; 295a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } else { 296a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata copy_sse_register(context, valuep, 0, sz, offset); 297a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return CLASS_SSE; 298a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 299a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 300a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 301a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata/* This allocates registers or stack space for another argument of the 302a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * class CLS. */ 303a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic enum arg_class 304a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataallocate_class(enum arg_class cls, struct fetch_context *context, 305a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct value *valuep, size_t sz, size_t offset, enum reg_pool pool) 306a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 307a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata switch (cls) { 308a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case CLASS_MEMORY: 309a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata allocate_stack_slot(context, valuep, sz, offset, 8); 310a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case CLASS_NO: 311a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return cls; 312a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 313a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case CLASS_INTEGER: 314a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return allocate_integer(context, valuep, sz, offset, pool); 315a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 316a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case CLASS_SSE: 317a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return allocate_sse(context, valuep, sz, offset, pool); 318a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 319a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case CLASS_X87: 320a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return allocate_x87(context, valuep, sz, offset, pool, 8); 321a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 322a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata abort(); 323a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 324a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 325a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic ssize_t 326929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataclassify(struct process *proc, struct fetch_context *context, 327a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct arg_type_info *info, struct value *valuep, enum arg_class classes[], 328a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t sz, size_t eightbytes); 329a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 330a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata/* This classifies one eightbyte part of an array or struct. */ 331a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic ssize_t 332929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataclassify_eightbyte(struct process *proc, struct fetch_context *context, 333a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct arg_type_info *info, struct value *valuep, 334a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata enum arg_class *classp, size_t start, size_t end, 335a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct arg_type_info *(*getter)(struct arg_type_info *, 336a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t)) 337a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 338a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t i; 339a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata enum arg_class cls = CLASS_NO; 340a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata for (i = start; i < end; ++i) { 341a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata enum arg_class cls2; 342a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct arg_type_info *info2 = getter(info, i); 343a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t sz = type_sizeof(proc, info2); 344a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (sz == (size_t)-1) 345a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return -1; 346a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (classify(proc, context, info2, valuep, &cls2, sz, 1) < 0) 347a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return -1; 348a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 349a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (cls == CLASS_NO) 350a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata cls = cls2; 351a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata else if (cls2 == CLASS_NO || cls == cls2) 352a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata ; 353a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata else if (cls == CLASS_MEMORY || cls2 == CLASS_MEMORY) 354a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata cls = CLASS_MEMORY; 355a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata else if (cls == CLASS_INTEGER || cls2 == CLASS_INTEGER) 356a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata cls = CLASS_INTEGER; 357a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata else 358a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata cls = CLASS_SSE; 359a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 360a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 361a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata *classp = cls; 362a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return 1; 363a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 364a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 365a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata/* This classifies small arrays and structs. */ 366a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic ssize_t 367929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataclassify_eightbytes(struct process *proc, struct fetch_context *context, 368a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct arg_type_info *info, struct value *valuep, 369a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata enum arg_class classes[], size_t elements, 370a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t eightbytes, 371a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct arg_type_info *(*getter)(struct arg_type_info *, 372a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t)) 373a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 374a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (eightbytes > 1) { 375a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* Where the second eightbyte starts. Number of the 376a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * first element in the structure that belongs to the 377a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * second eightbyte. */ 378a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t start_2nd = 0; 379a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t i; 380a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata for (i = 0; i < elements; ++i) 381a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (type_offsetof(proc, info, i) >= 8) { 382a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata start_2nd = i; 383a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata break; 384a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 385a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 386a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata enum arg_class cls1, cls2; 387a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (classify_eightbyte(proc, context, info, valuep, &cls1, 388a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 0, start_2nd, getter) < 0 389a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata || classify_eightbyte(proc, context, info, valuep, &cls2, 390a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata start_2nd, elements, getter) < 0) 391a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return -1; 392a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 393a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (cls1 == CLASS_MEMORY || cls2 == CLASS_MEMORY) { 394a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata classes[0] = CLASS_MEMORY; 395a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return 1; 396a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 397a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 398a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata classes[0] = cls1; 399a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata classes[1] = cls2; 400a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return 2; 401a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 402a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 403a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return classify_eightbyte(proc, context, info, valuep, classes, 404a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 0, elements, getter); 405a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 406a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 407a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic struct arg_type_info * 408a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataget_array_field(struct arg_type_info *info, size_t emt) 409a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 410a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return info->u.array_info.elt_type; 411a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 412a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 41378ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machatastatic int 41478ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machataflatten_structure(struct arg_type_info *flattened, struct arg_type_info *info) 41578ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata{ 41678ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata size_t i; 41778ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata for (i = 0; i < type_struct_size(info); ++i) { 41878ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata struct arg_type_info *field = type_struct_get(info, i); 41978ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata assert(field != NULL); 42078ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata switch (field->type) { 42178ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata case ARGTYPE_STRUCT: 42278ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata if (flatten_structure(flattened, field) < 0) 42378ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata return -1; 42478ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata break; 42578ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata 42678ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata default: 42778ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata if (type_struct_add(flattened, field, 0) < 0) 42878ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata return -1; 42978ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata } 43078ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata } 43178ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata return 0; 43278ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata} 43378ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata 434a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic ssize_t 435929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataclassify(struct process *proc, struct fetch_context *context, 436a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct arg_type_info *info, struct value *valuep, enum arg_class classes[], 437a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t sz, size_t eightbytes) 438a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 439a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata switch (info->type) { 44078ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata struct arg_type_info flattened; 441a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_VOID: 442a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return 0; 443a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 444a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_CHAR: 445a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_SHORT: 446a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_USHORT: 447a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_INT: 448a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_UINT: 449a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_LONG: 450a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_ULONG: 451a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 452a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_POINTER: 453a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* and LONGLONG */ 454a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* CLASS_INTEGER */ 455a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata classes[0] = CLASS_INTEGER; 456a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return 1; 457a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 458a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_FLOAT: 459a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_DOUBLE: 460a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* and DECIMAL, and _m64 */ 461a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata classes[0] = CLASS_SSE; 462a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return 1; 463a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 464a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_ARRAY: 465a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* N.B. this cannot be top-level array, those decay to 466a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * pointers. Therefore, it must be inside structure 467a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * that's at most 2 eightbytes long. */ 468a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 469a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* Structures with flexible array members can't be 470a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * passed by value. */ 471a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata assert(expr_is_compile_constant(info->u.array_info.length)); 472a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 473a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata long l; 474a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (expr_eval_constant(info->u.array_info.length, &l) < 0) 475a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return -1; 476a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 477a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return classify_eightbytes(proc, context, info, valuep, classes, 478a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata (size_t)l, eightbytes, 479a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata get_array_field); 480a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 481a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_STRUCT: 48278ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata /* N.B. "big" structs are dealt with in the caller. 48378ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata * 48478ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata * First, we need to flatten the structure. In 48578ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata * struct(float,struct(float,float)), first two floats 48678ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata * both belong to the same eightbyte. */ 48778ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata type_init_struct(&flattened); 48878ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata 48978ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata ssize_t ret; 49078ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata if (flatten_structure(&flattened, info) < 0) { 49178ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata ret = -1; 49278ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata goto done; 49378ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata } 49478ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata ret = classify_eightbytes(proc, context, &flattened, 49578ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata valuep, classes, 49678ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata type_struct_size(&flattened), 49778ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata eightbytes, type_struct_get); 49878ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata done: 49978ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata type_destroy(&flattened); 50078ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata return ret; 5015b5c256d0e9076e745908a43acc46353265a5608Edgar E. Iglesias 5025b5c256d0e9076e745908a43acc46353265a5608Edgar E. Iglesias default: 5035b5c256d0e9076e745908a43acc46353265a5608Edgar E. Iglesias /* Unsupported type. */ 5045b5c256d0e9076e745908a43acc46353265a5608Edgar E. Iglesias assert(info->type != info->type); 5055b5c256d0e9076e745908a43acc46353265a5608Edgar E. Iglesias abort(); 506a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 507a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata abort(); 508a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 509a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 510a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic ssize_t 511a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatapass_by_reference(struct value *valuep, enum arg_class classes[]) 512a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 513a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (valuep != NULL && value_pass_by_reference(valuep) < 0) 514a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return -1; 515a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata classes[0] = CLASS_INTEGER; 516a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return 1; 517a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 518a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 519a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic ssize_t 520929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataclassify_argument(struct process *proc, struct fetch_context *context, 521a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct arg_type_info *info, struct value *valuep, 522a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata enum arg_class classes[], size_t *sizep) 523a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 524a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t sz = type_sizeof(proc, info); 525a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (sz == (size_t)-1) 526a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return -1; 527a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata *sizep = sz; 528a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 529a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t eightbytes = (sz + 7) / 8; /* Round up. */ 530a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 531a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* Arrays decay into pointers. */ 532a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata assert(info->type != ARGTYPE_ARRAY); 533a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 534a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (info->type == ARGTYPE_STRUCT) { 535a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (eightbytes > 2 || contains_unaligned_fields(info)) { 536a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata classes[0] = CLASS_MEMORY; 537a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return 1; 538a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 539a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 540a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (has_nontrivial_ctor_dtor(info)) 541a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return pass_by_reference(valuep, classes); 542a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 543a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 544a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return classify(proc, context, info, valuep, classes, sz, eightbytes); 545a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 546a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 547a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic int 548929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatafetch_register_banks(struct process *proc, struct fetch_context *context, 549a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata int floating) 550a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 551a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (ptrace(PTRACE_GETREGS, proc->pid, 0, &context->iregs) < 0) 552a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return -1; 553a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata context->ireg = 0; 554a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 555a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (floating) { 556a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (ptrace(PTRACE_GETFPREGS, proc->pid, 557a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 0, &context->fpregs) < 0) 558a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return -1; 559a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata context->freg = 0; 560a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } else { 561a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata context->freg = -1; 562a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 563a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 564a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return 0; 565a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 566a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 567a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic int 568a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataarch_fetch_arg_next_32(struct fetch_context *context, enum tof type, 569929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata struct process *proc, struct arg_type_info *info, 570a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct value *valuep) 571a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 572a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t sz = type_sizeof(proc, info); 573a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (sz == (size_t)-1) 574a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return -1; 575a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 576a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata allocate_stack_slot(context, valuep, sz, 0, 4); 577a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 578a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return 0; 579a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 580a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 581a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic int 582a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataarch_fetch_retval_32(struct fetch_context *context, enum tof type, 583929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata struct process *proc, struct arg_type_info *info, 584a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct value *valuep) 585a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 586a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (fetch_register_banks(proc, context, type == LT_TOF_FUNCTIONR) < 0) 587a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return -1; 588a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 589ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata struct value *retval = &context->u.ix86.retval; 590a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (retval->type != NULL) { 591a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* Struct return value was extracted when in fetch 592a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * init. */ 593ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata memcpy(valuep, &context->u.ix86.retval, sizeof(*valuep)); 594a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return 0; 595a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 596a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 597a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t sz = type_sizeof(proc, info); 598a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (sz == (size_t)-1) 599a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return -1; 600a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (value_reserve(valuep, sz) == NULL) 601a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return -1; 602a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 603a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata switch (info->type) { 604a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata enum arg_class cls; 605a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_VOID: 606a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return 0; 607a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 608a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_INT: 609a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_UINT: 610a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_LONG: 611a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_ULONG: 612a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_CHAR: 613a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_SHORT: 614a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_USHORT: 615a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_POINTER: 616a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata cls = allocate_integer(context, valuep, sz, 0, POOL_RETVAL); 617a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata assert(cls == CLASS_INTEGER); 618a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return 0; 619a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 620a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_FLOAT: 621a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_DOUBLE: 622a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata cls = allocate_x87(context, valuep, sz, 0, POOL_RETVAL, 4); 623a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata assert(cls == CLASS_X87); 624a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return 0; 625a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 626a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case ARGTYPE_STRUCT: /* Handled above. */ 6275b5c256d0e9076e745908a43acc46353265a5608Edgar E. Iglesias default: 628a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata assert(!"Unexpected i386 retval type!"); 629a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata abort(); 630a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 631a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 632a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata abort(); 633a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 634a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 635bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machatastatic arch_addr_t 636ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machatafetch_stack_pointer(struct fetch_context *context) 637ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata{ 638bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata arch_addr_t sp; 639ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#ifdef __x86_64__ 640bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata sp = (arch_addr_t)context->iregs.rsp; 641ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#else 642bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata sp = (arch_addr_t)context->iregs.esp; 643ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif 644ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata return sp; 645ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata} 646ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata 647a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastruct fetch_context * 648a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataarch_fetch_arg_init_32(struct fetch_context *context, 649929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata enum tof type, struct process *proc, 650a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct arg_type_info *ret_info) 651a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 652ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata context->stack_pointer = fetch_stack_pointer(context) + 4; 653a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 654a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t sz = type_sizeof(proc, ret_info); 655a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (sz == (size_t)-1) 656a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return NULL; 657a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 658ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata struct value *retval = &context->u.ix86.retval; 659a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (ret_info->type == ARGTYPE_STRUCT) { 660a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata value_init(retval, proc, NULL, ret_info, 0); 661a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 662a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata enum arg_class dummy[2]; 663a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (pass_by_reference(retval, dummy) < 0) 664a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return NULL; 665a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata allocate_stack_slot(context, retval, 4, 0, 4); 666a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 667a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } else { 668a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata value_init_detached(retval, NULL, NULL, 0); 669a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 670a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 671a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return context; 672a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 673a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 674a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastruct fetch_context * 675a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataarch_fetch_arg_init_64(struct fetch_context *ctx, enum tof type, 676929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata struct process *proc, struct arg_type_info *ret_info) 677a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 678a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* The first stack slot holds a return address. */ 679ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata ctx->stack_pointer = fetch_stack_pointer(ctx) + 8; 680a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 681a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t size; 682a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata ctx->u.x86_64.num_ret_classes 683a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata = classify_argument(proc, ctx, ret_info, NULL, 684a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata ctx->u.x86_64.ret_classes, &size); 685a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (ctx->u.x86_64.num_ret_classes == -1) 686a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return NULL; 687a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 688a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* If the class is MEMORY, then the first argument is a hidden 689a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * pointer to the allocated storage. */ 690a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (ctx->u.x86_64.num_ret_classes > 0 691a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata && ctx->u.x86_64.ret_classes[0] == CLASS_MEMORY) { 692a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* MEMORY should be the sole class. */ 693a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata assert(ctx->u.x86_64.num_ret_classes == 1); 694a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata allocate_integer(ctx, NULL, size, 0, POOL_FUNCALL); 695a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 696a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 697a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return ctx; 698a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 699a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 700a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastruct fetch_context * 701929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataarch_fetch_arg_init(enum tof type, struct process *proc, 702a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct arg_type_info *ret_info) 703a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 704a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct fetch_context *ctx = malloc(sizeof(*ctx)); 705a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (ctx == NULL) 706a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return NULL; 707a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 708a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata assert(type != LT_TOF_FUNCTIONR 709a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata && type != LT_TOF_SYSCALLR); 710a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (fetch_register_banks(proc, ctx, type == LT_TOF_FUNCTION) < 0) { 711a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata fail: 712a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata free(ctx); 713a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return NULL; 714a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 715a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 716a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct fetch_context *ret; 717a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (proc->e_machine == EM_386) 718a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata ret = arch_fetch_arg_init_32(ctx, type, proc, ret_info); 719a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata else 720a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata ret = arch_fetch_arg_init_64(ctx, type, proc, ret_info); 721a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (ret == NULL) 722a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata goto fail; 723a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return ret; 724a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 725a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 726a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastruct fetch_context * 727929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataarch_fetch_arg_clone(struct process *proc, struct fetch_context *context) 728a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 729a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct fetch_context *ret = malloc(sizeof(*ret)); 730a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (ret == NULL) 731a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return NULL; 732a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return memcpy(ret, context, sizeof(*ret)); 733a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 734a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 735a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic int 736a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataarch_fetch_pool_arg_next(struct fetch_context *context, enum tof type, 737929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata struct process *proc, struct arg_type_info *info, 738a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct value *valuep, enum reg_pool pool) 739a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 740a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata enum arg_class classes[2]; 741a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t sz, sz1; 742a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata ssize_t i; 743a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata ssize_t nclasses = classify_argument(proc, context, info, valuep, 744a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata classes, &sz); 745a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (nclasses == -1) 746a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return -1; 747a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (value_reserve(valuep, sz) == NULL) 748a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return -1; 749a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 750a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata /* If there are no registers available for any eightbyte of an 751a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * argument, the whole argument is passed on the stack. If 752a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * registers have already been assigned for some eightbytes of 753a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * such an argument, the assignments get reverted. */ 754a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct fetch_context tmp_context = *context; 755a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata int revert; 756a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (nclasses == 1) { 757a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata revert = allocate_class(classes[0], &tmp_context, 758a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata valuep, sz, 0, pool) != classes[0]; 759a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } else { 760a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata revert = 0; 761a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata for (i = 0; i < nclasses; ++i) { 762a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata sz1 = (size_t)(8 * (i + 1)) > sz ? sz - 8 * i : 8; 763a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (allocate_class(classes[i], &tmp_context, valuep, 764a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata sz1, 8 * i, pool) != classes[i]) 765a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata revert = 1; 766a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 767a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 768a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 769a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (nclasses > 1 && revert) 770a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata allocate_class(CLASS_MEMORY, context, valuep, sz, 0, pool); 771a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata else 772a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata *context = tmp_context; /* Commit. */ 773a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 774a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return 0; 775a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 776a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 777a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataint 778a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataarch_fetch_fun_retval(struct fetch_context *context, enum tof type, 779929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata struct process *proc, struct arg_type_info *info, 780a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct value *valuep) 781a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 782a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata assert(type != LT_TOF_FUNCTION 783a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata && type != LT_TOF_SYSCALL); 784a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (value_reserve(valuep, 8 * context->u.x86_64.num_ret_classes) == NULL 785a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata || fetch_register_banks(proc, context, 786a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata type == LT_TOF_FUNCTIONR) < 0) 787a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return -1; 788a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 789a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (context->u.x86_64.num_ret_classes == 1 790a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata && context->u.x86_64.ret_classes[0] == CLASS_MEMORY) 791a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata pass_by_reference(valuep, context->u.x86_64.ret_classes); 792a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 793a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t sz = type_sizeof(proc, valuep->type); 794a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (sz == (size_t)-1) 795a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return -1; 796a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 797a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata ssize_t i; 798a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata size_t sz1 = context->u.x86_64.num_ret_classes == 1 ? sz : 8; 799a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata for (i = 0; i < context->u.x86_64.num_ret_classes; ++i) { 800a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata enum arg_class cls 801a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata = allocate_class(context->u.x86_64.ret_classes[i], 802a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata context, valuep, sz1, 803a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 8 * i, POOL_RETVAL); 804a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata assert(cls == context->u.x86_64.ret_classes[i]); 805a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 806a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return 0; 807a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 808a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 809a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataint 810a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataarch_fetch_arg_next(struct fetch_context *context, enum tof type, 811929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata struct process *proc, struct arg_type_info *info, 812a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct value *valuep) 813a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 814a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (proc->e_machine == EM_386) 815a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return arch_fetch_arg_next_32(context, type, proc, 816a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata info, valuep); 817a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 818a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata switch (type) { 819a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case LT_TOF_FUNCTION: 820a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case LT_TOF_FUNCTIONR: 821a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return arch_fetch_pool_arg_next(context, type, proc, 822a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata info, valuep, POOL_FUNCALL); 823a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 824a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case LT_TOF_SYSCALL: 825a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata case LT_TOF_SYSCALLR: 826a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return arch_fetch_pool_arg_next(context, type, proc, 827a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata info, valuep, POOL_SYSCALL); 828a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata } 829a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 830a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata abort(); 831a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 832a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 833a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataint 834a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataarch_fetch_retval(struct fetch_context *context, enum tof type, 835929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata struct process *proc, struct arg_type_info *info, 836a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata struct value *valuep) 837a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 838a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (proc->e_machine == EM_386) 839a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return arch_fetch_retval_32(context, type, proc, info, valuep); 840a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 841a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata return arch_fetch_fun_retval(context, type, proc, info, valuep); 842a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 843a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata 844a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatavoid 845a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataarch_fetch_arg_done(struct fetch_context *context) 846a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{ 847a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata if (context != NULL) 848a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata free(context); 849a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata} 850