fetch.c revision de98cb698d69ccbbb4388a6401a27897ba02371a
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
61de98cb698d69ccbbb4388a6401a27897ba02371aPetr Machata	arch_addr_t 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