1a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata/*
2a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * This file is part of ltrace.
35069ef8f498e5189de0789d79485f39b76c621d4Petr Machata * Copyright (C) 2011,2012,2013 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.  */
645069ef8f498e5189de0789d79485f39b76c621d4Petr Machata	int machine;
65a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
66a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	union {
67a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		struct {
68a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			/* Storage classes for return type.  We need
69a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			 * to compute them anyway, so let's keep them
70a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			 * around.  */
71a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			enum arg_class ret_classes[2];
72a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			ssize_t num_ret_classes;
73a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		} x86_64;
74a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		struct {
75a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			struct value retval;
76ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata		} ix86;
77a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	} u;
78a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata};
79a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
80ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#ifndef __x86_64__
81ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata__attribute__((noreturn)) static void
82ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machatai386_unreachable(void)
83ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata{
84ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	abort();
85ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata}
86ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif
87ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata
88a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic int
89a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatacontains_unaligned_fields(struct arg_type_info *info)
90a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
91a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	/* XXX currently we don't support structure alignment.  */
92a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	return 0;
93a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
94a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
95a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic int
96a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatahas_nontrivial_ctor_dtor(struct arg_type_info *info)
97a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
98a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	/* XXX another unsupported aspect of type info.  We might call
99a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 * these types "class" instead of "struct" in the config
100a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 * file.  */
101a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	return 0;
102a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
103a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
104a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic void
105a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatacopy_int_register(struct fetch_context *context,
106a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		  struct value *valuep, unsigned long val, size_t offset)
107a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
108a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (valuep != NULL) {
109a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		unsigned char *buf = value_get_raw_data(valuep);
110a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		memcpy(buf + offset, &val, sizeof(val));
111a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
112a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	context->ireg++;
113a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
114a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
115a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic void
116a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatacopy_sse_register(struct fetch_context *context, struct value *valuep,
117a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		  int half, size_t sz, size_t offset)
118a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
119ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#ifdef __x86_64__
120a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	union {
121a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		uint32_t sse[4];
122a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		long halves[2];
123a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	} u;
124a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	size_t off = 4 * context->freg++;
125a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	memcpy(u.sse, context->fpregs.xmm_space + off, sizeof(u.sse));
126a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
127a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (valuep != NULL) {
128a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		unsigned char *buf = value_get_raw_data(valuep);
129a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		memcpy(buf + offset, u.halves + half, sz);
130a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
131ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#else
132ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	i386_unreachable();
133ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif
134a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
135a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
136a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic void
137a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataallocate_stack_slot(struct fetch_context *context,
138a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		    struct value *valuep, size_t sz, size_t offset,
139a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		    size_t archw)
140a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
14184c8c722654548ed1cef5ba183a2198aad089836Petr Machata	assert(valuep != NULL);
142a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	size_t a = type_alignof(valuep->inferior, valuep->type);
143a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (a < archw)
144a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		a = archw;
145a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	context->stack_pointer
146a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		= (void *)align((unsigned long)context->stack_pointer, a);
147a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
14884c8c722654548ed1cef5ba183a2198aad089836Petr Machata	value_in_inferior(valuep, context->stack_pointer);
149a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	context->stack_pointer += sz;
150a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
151a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
152a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic enum arg_class
153a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataallocate_x87(struct fetch_context *context, struct value *valuep,
154a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	     size_t sz, size_t offset, enum reg_pool pool, size_t archw)
155a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
156a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	/* Both i386 and x86_64 ABI only ever really use x87 registers
157a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 * to return values.  Otherwise, the parameter is treated as
158a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 * if it were CLASS_MEMORY.  On x86_64 x87 registers are only
159a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 * used for returning long double values, which we currently
160a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 * don't support.  */
161a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
162a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (pool != POOL_RETVAL) {
163a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		allocate_stack_slot(context, valuep, sz, offset, archw);
164a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return CLASS_MEMORY;
165a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
166a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
167a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
168a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	/* If the class is X87, the value is returned on the X87 stack
169a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 * in %st0 as 80-bit x87 number.
170a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 *
171a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 * If the class is X87UP, the value is returned together with
172a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 * the previous X87 value in %st0.
173a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 *
174a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 * If the class is COMPLEX_X87, the real part of the value is
175a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 * returned in %st0 and the imaginary part in %st1.  */
176a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
177a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (valuep != NULL) {
178a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		union {
179a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			long double ld;
180a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			double d;
181a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			float f;
182a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			char buf[0];
183a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		} u;
184a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
185a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		/* The x87 floating point value is in long double
186a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		 * format, so we need to convert in to the right type.
187a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		 * Alternatively we might just leave it as is and
188a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		 * smuggle the long double type into the value (via
189a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		 * value_set_type), but for that we first need to
190a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		 * support long double in the first place.  */
191a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
192ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#ifdef __x86_64__
193ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata		unsigned int *reg;
194ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#else
195ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata		long int *reg;
196ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif
197ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata		reg = &context->fpregs.st_space[0];
198a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		memcpy(&u.ld, reg, sizeof(u));
199a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		if (valuep->type->type == ARGTYPE_FLOAT)
200a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			u.f = (float)u.ld;
201a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		else if (valuep->type->type == ARGTYPE_DOUBLE)
202a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			u.d = (double)u.ld;
203a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		else
204a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			assert(!"Unexpected floating type!"), abort();
205a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
206a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		unsigned char *buf = value_get_raw_data(valuep);
207a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		memcpy(buf + offset, u.buf, sz);
208a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
209a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	return CLASS_X87;
210a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
211a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
212a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic enum arg_class
213a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataallocate_integer(struct fetch_context *context, struct value *valuep,
214a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		 size_t sz, size_t offset, enum reg_pool pool)
215a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
216a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata#define HANDLE(NUM, WHICH)						\
217a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case NUM:							\
218a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		copy_int_register(context, valuep,			\
219a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata				  context->iregs.WHICH, offset);	\
220a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return CLASS_INTEGER
221a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
222a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	switch (pool) {
223a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case POOL_FUNCALL:
224ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#ifdef __x86_64__
225a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		switch (context->ireg) {
226a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			HANDLE(0, rdi);
227a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			HANDLE(1, rsi);
228a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			HANDLE(2, rdx);
229a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			HANDLE(3, rcx);
230a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			HANDLE(4, r8);
231a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			HANDLE(5, r9);
232a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		default:
233a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			allocate_stack_slot(context, valuep, sz, offset, 8);
234a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			return CLASS_MEMORY;
235a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		}
236ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#else
237ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata		i386_unreachable();
238ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif
239a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
240a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case POOL_SYSCALL:
241ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#ifdef __x86_64__
2425069ef8f498e5189de0789d79485f39b76c621d4Petr Machata		if (context->machine == EM_X86_64) {
2435069ef8f498e5189de0789d79485f39b76c621d4Petr Machata			switch (context->ireg) {
2445069ef8f498e5189de0789d79485f39b76c621d4Petr Machata				HANDLE(0, rdi);
2455069ef8f498e5189de0789d79485f39b76c621d4Petr Machata				HANDLE(1, rsi);
2465069ef8f498e5189de0789d79485f39b76c621d4Petr Machata				HANDLE(2, rdx);
2475069ef8f498e5189de0789d79485f39b76c621d4Petr Machata				HANDLE(3, r10);
2485069ef8f498e5189de0789d79485f39b76c621d4Petr Machata				HANDLE(4, r8);
2495069ef8f498e5189de0789d79485f39b76c621d4Petr Machata				HANDLE(5, r9);
2505069ef8f498e5189de0789d79485f39b76c621d4Petr Machata			default:
2515069ef8f498e5189de0789d79485f39b76c621d4Petr Machata				assert(!"More than six syscall arguments???");
2525069ef8f498e5189de0789d79485f39b76c621d4Petr Machata				abort();
2535069ef8f498e5189de0789d79485f39b76c621d4Petr Machata			}
254a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		}
2555069ef8f498e5189de0789d79485f39b76c621d4Petr Machata#endif
2565069ef8f498e5189de0789d79485f39b76c621d4Petr Machata		if (context->machine == EM_386) {
2575069ef8f498e5189de0789d79485f39b76c621d4Petr Machata
2585069ef8f498e5189de0789d79485f39b76c621d4Petr Machata#ifdef __x86_64__
2595069ef8f498e5189de0789d79485f39b76c621d4Petr Machata# define HANDLE32(NUM, WHICH) HANDLE(NUM, r##WHICH)
260ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#else
2615069ef8f498e5189de0789d79485f39b76c621d4Petr Machata# define HANDLE32(NUM, WHICH) HANDLE(NUM, e##WHICH)
262ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif
263a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
2645069ef8f498e5189de0789d79485f39b76c621d4Petr Machata			switch (context->ireg) {
2655069ef8f498e5189de0789d79485f39b76c621d4Petr Machata				HANDLE32(0, bx);
2665069ef8f498e5189de0789d79485f39b76c621d4Petr Machata				HANDLE32(1, cx);
2675069ef8f498e5189de0789d79485f39b76c621d4Petr Machata				HANDLE32(2, dx);
2685069ef8f498e5189de0789d79485f39b76c621d4Petr Machata				HANDLE32(3, si);
2695069ef8f498e5189de0789d79485f39b76c621d4Petr Machata				HANDLE32(4, di);
2705069ef8f498e5189de0789d79485f39b76c621d4Petr Machata				HANDLE32(5, bp);
2715069ef8f498e5189de0789d79485f39b76c621d4Petr Machata			default:
2725069ef8f498e5189de0789d79485f39b76c621d4Petr Machata				assert(!"More than six syscall arguments???");
2735069ef8f498e5189de0789d79485f39b76c621d4Petr Machata				abort();
2745069ef8f498e5189de0789d79485f39b76c621d4Petr Machata			}
2755069ef8f498e5189de0789d79485f39b76c621d4Petr Machata#undef HANDLE32
2765069ef8f498e5189de0789d79485f39b76c621d4Petr Machata		}
2775069ef8f498e5189de0789d79485f39b76c621d4Petr Machata
278a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case POOL_RETVAL:
279a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		switch (context->ireg) {
280ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#ifdef __x86_64__
281a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			HANDLE(0, rax);
282a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			HANDLE(1, rdx);
283ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#else
284ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata			HANDLE(0, eax);
285ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif
286a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		default:
287ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata			assert(!"Too many return value classes.");
288a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			abort();
289a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		}
290a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
291a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
292a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	abort();
293a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
294a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata#undef HANDLE
295a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
296a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
297a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic enum arg_class
298a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataallocate_sse(struct fetch_context *context, struct value *valuep,
299a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	     size_t sz, size_t offset, enum reg_pool pool)
300a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
301a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	size_t num_regs = 0;
302a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	switch (pool) {
303a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case POOL_FUNCALL:
304a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		num_regs = 8;
305a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case POOL_SYSCALL:
306a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		break;
307a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case POOL_RETVAL:
308a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		num_regs = 2;
309a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
310a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
311a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (context->freg >= num_regs) {
312a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		/* We shouldn't see overflow for RETVAL or SYSCALL
313a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		 * pool.  */
314a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		assert(pool == POOL_FUNCALL);
315a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		allocate_stack_slot(context, valuep, sz, offset, 8);
316a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return CLASS_MEMORY;
317a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	} else {
318a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		copy_sse_register(context, valuep, 0, sz, offset);
319a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return CLASS_SSE;
320a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
321a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
322a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
323a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata/* This allocates registers or stack space for another argument of the
324a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata * class CLS.  */
325a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic enum arg_class
326a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataallocate_class(enum arg_class cls, struct fetch_context *context,
327a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	       struct value *valuep, size_t sz, size_t offset, enum reg_pool pool)
328a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
329a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	switch (cls) {
330a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case CLASS_MEMORY:
331a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		allocate_stack_slot(context, valuep, sz, offset, 8);
332a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case CLASS_NO:
333a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return cls;
334a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
335a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case CLASS_INTEGER:
336a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return allocate_integer(context, valuep, sz, offset, pool);
337a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
338a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case CLASS_SSE:
339a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return allocate_sse(context, valuep, sz, offset, pool);
340a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
341a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case CLASS_X87:
342a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return allocate_x87(context, valuep, sz, offset, pool, 8);
343a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
344a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	abort();
345a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
346a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
347a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic ssize_t
348929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataclassify(struct process *proc, struct fetch_context *context,
34952173f05eada6fab209e4f890b507ebaec32c163Petr Machata	 struct arg_type_info *info, enum arg_class classes[],
350a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 size_t sz, size_t eightbytes);
351a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
352a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata/* This classifies one eightbyte part of an array or struct.  */
353a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic ssize_t
354929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataclassify_eightbyte(struct process *proc, struct fetch_context *context,
35552173f05eada6fab209e4f890b507ebaec32c163Petr Machata		   struct arg_type_info *info,
356a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		   enum arg_class *classp, size_t start, size_t end,
357a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		   struct arg_type_info *(*getter)(struct arg_type_info *,
358a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata						   size_t))
359a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
360a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	size_t i;
361a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	enum arg_class cls = CLASS_NO;
362a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	for (i = start; i < end; ++i) {
363a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		enum arg_class cls2;
364a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		struct arg_type_info *info2 = getter(info, i);
365a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		size_t sz = type_sizeof(proc, info2);
366a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		if (sz == (size_t)-1)
367a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			return -1;
36852173f05eada6fab209e4f890b507ebaec32c163Petr Machata		if (classify(proc, context, info2, &cls2, sz, 1) < 0)
369a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			return -1;
370a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
371a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		if (cls == CLASS_NO)
372a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			cls = cls2;
373a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		else if (cls2 == CLASS_NO || cls == cls2)
374a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			;
375a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		else if (cls == CLASS_MEMORY || cls2 == CLASS_MEMORY)
376a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			cls = CLASS_MEMORY;
377a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		else if (cls == CLASS_INTEGER || cls2 == CLASS_INTEGER)
378a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			cls = CLASS_INTEGER;
379a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		else
380a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			cls = CLASS_SSE;
381a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
382a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
383a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	*classp = cls;
384a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	return 1;
385a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
386a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
387a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata/* This classifies small arrays and structs.  */
388a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic ssize_t
389929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataclassify_eightbytes(struct process *proc, struct fetch_context *context,
39052173f05eada6fab209e4f890b507ebaec32c163Petr Machata		    struct arg_type_info *info,
391a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		    enum arg_class classes[], size_t elements,
392a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		    size_t eightbytes,
393a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		    struct arg_type_info *(*getter)(struct arg_type_info *,
394a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata						    size_t))
395a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
396a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (eightbytes > 1) {
397a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		/* Where the second eightbyte starts.  Number of the
398a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		 * first element in the structure that belongs to the
399a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		 * second eightbyte.  */
400a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		size_t start_2nd = 0;
401a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		size_t i;
402a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		for (i = 0; i < elements; ++i)
403a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			if (type_offsetof(proc, info, i) >= 8) {
404a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata				start_2nd = i;
405a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata				break;
406a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			}
407a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
408a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		enum arg_class cls1, cls2;
40952173f05eada6fab209e4f890b507ebaec32c163Petr Machata		if (classify_eightbyte(proc, context, info, &cls1,
410a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata				       0, start_2nd, getter) < 0
41152173f05eada6fab209e4f890b507ebaec32c163Petr Machata		    || classify_eightbyte(proc, context, info, &cls2,
412a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata					  start_2nd, elements, getter) < 0)
413a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			return -1;
414a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
415a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		if (cls1 == CLASS_MEMORY || cls2 == CLASS_MEMORY) {
416a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			classes[0] = CLASS_MEMORY;
417a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			return 1;
418a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		}
419a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
420a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		classes[0] = cls1;
421a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		classes[1] = cls2;
422a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return 2;
423a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
424a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
42552173f05eada6fab209e4f890b507ebaec32c163Petr Machata	return classify_eightbyte(proc, context, info, classes,
426a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata				  0, elements, getter);
427a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
428a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
429a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic struct arg_type_info *
430a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataget_array_field(struct arg_type_info *info, size_t emt)
431a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
432a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	return info->u.array_info.elt_type;
433a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
434a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
43578ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machatastatic int
43678ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machataflatten_structure(struct arg_type_info *flattened, struct arg_type_info *info)
43778ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata{
43878ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata	size_t i;
43978ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata	for (i = 0; i < type_struct_size(info); ++i) {
44078ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		struct arg_type_info *field = type_struct_get(info, i);
44178ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		assert(field != NULL);
44278ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		switch (field->type) {
44378ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		case ARGTYPE_STRUCT:
44478ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata			if (flatten_structure(flattened, field) < 0)
44578ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata				return -1;
44678ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata			break;
44778ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata
44878ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		default:
44978ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata			if (type_struct_add(flattened, field, 0) < 0)
45078ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata				return -1;
45178ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		}
45278ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata	}
45378ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata	return 0;
45478ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata}
45578ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata
456a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic ssize_t
457929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataclassify(struct process *proc, struct fetch_context *context,
45852173f05eada6fab209e4f890b507ebaec32c163Petr Machata	 struct arg_type_info *info, enum arg_class classes[],
459a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 size_t sz, size_t eightbytes)
460a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
461a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	switch (info->type) {
46278ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		struct arg_type_info flattened;
463a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_VOID:
464a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return 0;
465a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
466a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_CHAR:
467a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_SHORT:
468a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_USHORT:
469a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_INT:
470a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_UINT:
471a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_LONG:
472a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_ULONG:
473a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
474a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_POINTER:
475a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		/* and LONGLONG */
476a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		/* CLASS_INTEGER */
477a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		classes[0] = CLASS_INTEGER;
478a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return 1;
479a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
480a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_FLOAT:
481a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_DOUBLE:
482a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		/* and DECIMAL, and _m64 */
483a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		classes[0] = CLASS_SSE;
484a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return 1;
485a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
486a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_ARRAY:
487a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		/* N.B. this cannot be top-level array, those decay to
488a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		 * pointers.  Therefore, it must be inside structure
489a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		 * that's at most 2 eightbytes long.  */
490a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
491a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		/* Structures with flexible array members can't be
492a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		 * passed by value.  */
493a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		assert(expr_is_compile_constant(info->u.array_info.length));
494a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
495a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		long l;
496a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		if (expr_eval_constant(info->u.array_info.length, &l) < 0)
497a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			return -1;
498a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
49952173f05eada6fab209e4f890b507ebaec32c163Petr Machata		return classify_eightbytes(proc, context, info, classes,
500a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata					   (size_t)l, eightbytes,
501a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata					   get_array_field);
502a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
503a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_STRUCT:
50478ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		/* N.B. "big" structs are dealt with in the caller.
50578ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		 *
50678ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		 * First, we need to flatten the structure.  In
50778ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		 * struct(float,struct(float,float)), first two floats
50878ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		 * both belong to the same eightbyte.  */
50978ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		type_init_struct(&flattened);
51078ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata
51178ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		ssize_t ret;
51278ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		if (flatten_structure(&flattened, info) < 0) {
51378ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata			ret = -1;
51478ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata			goto done;
51578ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		}
51678ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		ret = classify_eightbytes(proc, context, &flattened,
51752173f05eada6fab209e4f890b507ebaec32c163Petr Machata					  classes,
51878ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata					  type_struct_size(&flattened),
51978ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata					  eightbytes, type_struct_get);
52078ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata	done:
52178ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		type_destroy(&flattened);
52278ed40f161c102a10c6033c28ad9a80e5ffe9550Petr Machata		return ret;
5235b5c256d0e9076e745908a43acc46353265a5608Edgar E. Iglesias
5245b5c256d0e9076e745908a43acc46353265a5608Edgar E. Iglesias	default:
5255b5c256d0e9076e745908a43acc46353265a5608Edgar E. Iglesias		/* Unsupported type.  */
5265b5c256d0e9076e745908a43acc46353265a5608Edgar E. Iglesias		assert(info->type != info->type);
5275b5c256d0e9076e745908a43acc46353265a5608Edgar E. Iglesias		abort();
528a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
529a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	abort();
530a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
531a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
532a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic ssize_t
533a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatapass_by_reference(struct value *valuep, enum arg_class classes[])
534a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
535a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (valuep != NULL && value_pass_by_reference(valuep) < 0)
536a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return -1;
537a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	classes[0] = CLASS_INTEGER;
538a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	return 1;
539a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
540a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
541a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic ssize_t
542929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataclassify_argument(struct process *proc, struct fetch_context *context,
543a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		  struct arg_type_info *info, struct value *valuep,
544a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		  enum arg_class classes[], size_t *sizep)
545a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
546a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	size_t sz = type_sizeof(proc, info);
547a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (sz == (size_t)-1)
548a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return -1;
549a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	*sizep = sz;
550a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
551a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	size_t eightbytes = (sz + 7) / 8;  /* Round up.  */
552a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
553a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	/* Arrays decay into pointers.  */
554a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	assert(info->type != ARGTYPE_ARRAY);
555a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
556a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (info->type == ARGTYPE_STRUCT) {
557a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		if (eightbytes > 2 || contains_unaligned_fields(info)) {
558a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			classes[0] = CLASS_MEMORY;
559a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			return 1;
560a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		}
561a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
562a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		if (has_nontrivial_ctor_dtor(info))
563a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			return pass_by_reference(valuep, classes);
564a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
565a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
56652173f05eada6fab209e4f890b507ebaec32c163Petr Machata	return classify(proc, context, info, classes, sz, eightbytes);
567a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
568a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
569a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic int
570929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatafetch_register_banks(struct process *proc, struct fetch_context *context,
571a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		     int floating)
572a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
573a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (ptrace(PTRACE_GETREGS, proc->pid, 0, &context->iregs) < 0)
574a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return -1;
575a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	context->ireg = 0;
576a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
577a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (floating) {
578a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		if (ptrace(PTRACE_GETFPREGS, proc->pid,
579a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			   0, &context->fpregs) < 0)
580a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			return -1;
581a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		context->freg = 0;
582a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	} else {
583a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		context->freg = -1;
584a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
585a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
586a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	return 0;
587a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
588a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
589a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic int
590a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataarch_fetch_arg_next_32(struct fetch_context *context, enum tof type,
591929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata		       struct process *proc, struct arg_type_info *info,
592a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		       struct value *valuep)
593a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
594a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	size_t sz = type_sizeof(proc, info);
595a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (sz == (size_t)-1)
596a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return -1;
5975069ef8f498e5189de0789d79485f39b76c621d4Petr Machata	if (value_reserve(valuep, sz) == NULL)
5985069ef8f498e5189de0789d79485f39b76c621d4Petr Machata		return -1;
5995069ef8f498e5189de0789d79485f39b76c621d4Petr Machata
6005069ef8f498e5189de0789d79485f39b76c621d4Petr Machata	if (type == LT_TOF_SYSCALL || type == LT_TOF_SYSCALLR) {
6015069ef8f498e5189de0789d79485f39b76c621d4Petr Machata		int cls = allocate_integer(context, valuep,
6025069ef8f498e5189de0789d79485f39b76c621d4Petr Machata					   sz, 0, POOL_SYSCALL);
6035069ef8f498e5189de0789d79485f39b76c621d4Petr Machata		assert(cls == CLASS_INTEGER);
6045069ef8f498e5189de0789d79485f39b76c621d4Petr Machata		return 0;
6055069ef8f498e5189de0789d79485f39b76c621d4Petr Machata	}
606a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
607a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	allocate_stack_slot(context, valuep, sz, 0, 4);
608a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
609a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	return 0;
610a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
611a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
612a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic int
613a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataarch_fetch_retval_32(struct fetch_context *context, enum tof type,
614929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata		     struct process *proc, struct arg_type_info *info,
615a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		     struct value *valuep)
616a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
617a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (fetch_register_banks(proc, context, type == LT_TOF_FUNCTIONR) < 0)
618a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return -1;
619a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
620ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	struct value *retval = &context->u.ix86.retval;
621a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (retval->type != NULL) {
622a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		/* Struct return value was extracted when in fetch
623a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		 * init.  */
624ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata		memcpy(valuep, &context->u.ix86.retval, sizeof(*valuep));
625a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return 0;
626a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
627a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
628a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	size_t sz = type_sizeof(proc, info);
629a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (sz == (size_t)-1)
630a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return -1;
631a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (value_reserve(valuep, sz) == NULL)
632a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return -1;
633a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
634a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	switch (info->type) {
635a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		enum arg_class cls;
636a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_VOID:
637a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return 0;
638a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
639a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_INT:
640a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_UINT:
641a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_LONG:
642a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_ULONG:
643a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_CHAR:
644a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_SHORT:
645a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_USHORT:
646a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_POINTER:
647a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		cls = allocate_integer(context, valuep, sz, 0, POOL_RETVAL);
648a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		assert(cls == CLASS_INTEGER);
649a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return 0;
650a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
651a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_FLOAT:
652a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_DOUBLE:
653a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		cls = allocate_x87(context, valuep, sz, 0, POOL_RETVAL, 4);
654a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		assert(cls == CLASS_X87);
655a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return 0;
656a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
657a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case ARGTYPE_STRUCT: /* Handled above.  */
6585b5c256d0e9076e745908a43acc46353265a5608Edgar E. Iglesias	default:
659a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		assert(!"Unexpected i386 retval type!");
660a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		abort();
661a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
662a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
663a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	abort();
664a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
665a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
666bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machatastatic arch_addr_t
667ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machatafetch_stack_pointer(struct fetch_context *context)
668ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata{
669bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	arch_addr_t sp;
670ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#ifdef __x86_64__
671bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	sp = (arch_addr_t)context->iregs.rsp;
672ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#else
673bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata	sp = (arch_addr_t)context->iregs.esp;
674ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata#endif
675ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	return sp;
676ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata}
677ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata
678a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastruct fetch_context *
679a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataarch_fetch_arg_init_32(struct fetch_context *context,
680929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata		       enum tof type, struct process *proc,
681a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		       struct arg_type_info *ret_info)
682a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
683ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	context->stack_pointer = fetch_stack_pointer(context) + 4;
684a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
685a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	size_t sz = type_sizeof(proc, ret_info);
686a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (sz == (size_t)-1)
687a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return NULL;
688a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
689ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	struct value *retval = &context->u.ix86.retval;
690a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (ret_info->type == ARGTYPE_STRUCT) {
691a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		value_init(retval, proc, NULL, ret_info, 0);
692a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
693a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		enum arg_class dummy[2];
694a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		if (pass_by_reference(retval, dummy) < 0)
695a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			return NULL;
696a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		allocate_stack_slot(context, retval, 4, 0, 4);
697a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
698a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	} else {
699a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		value_init_detached(retval, NULL, NULL, 0);
700a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
701a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
702a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	return context;
703a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
704a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
705a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastruct fetch_context *
706a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataarch_fetch_arg_init_64(struct fetch_context *ctx, enum tof type,
707929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata		       struct process *proc, struct arg_type_info *ret_info)
708a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
709a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	/* The first stack slot holds a return address.  */
710ddd96a3fbc7c54146d1d831810fc9e29c9bc3c76Petr Machata	ctx->stack_pointer = fetch_stack_pointer(ctx) + 8;
711a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
712a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	size_t size;
713a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	ctx->u.x86_64.num_ret_classes
714a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		= classify_argument(proc, ctx, ret_info, NULL,
715a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata				    ctx->u.x86_64.ret_classes, &size);
716a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (ctx->u.x86_64.num_ret_classes == -1)
717a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return NULL;
718a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
719a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	/* If the class is MEMORY, then the first argument is a hidden
720a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 * pointer to the allocated storage.  */
721a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (ctx->u.x86_64.num_ret_classes > 0
722a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	    && ctx->u.x86_64.ret_classes[0] == CLASS_MEMORY) {
723a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		/* MEMORY should be the sole class.  */
724a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		assert(ctx->u.x86_64.num_ret_classes == 1);
725a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		allocate_integer(ctx, NULL, size, 0, POOL_FUNCALL);
726a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
727a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
728a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	return ctx;
729a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
730a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
731a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastruct fetch_context *
732929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataarch_fetch_arg_init(enum tof type, struct process *proc,
733a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		    struct arg_type_info *ret_info)
734a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
735a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	struct fetch_context *ctx = malloc(sizeof(*ctx));
736a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (ctx == NULL)
737a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return NULL;
7385069ef8f498e5189de0789d79485f39b76c621d4Petr Machata	ctx->machine = proc->e_machine;
739a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
740a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	assert(type != LT_TOF_FUNCTIONR
741a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	       && type != LT_TOF_SYSCALLR);
742a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (fetch_register_banks(proc, ctx, type == LT_TOF_FUNCTION) < 0) {
743a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	fail:
744a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		free(ctx);
745a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return NULL;
746a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
747a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
748a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	struct fetch_context *ret;
749a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (proc->e_machine == EM_386)
750a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		ret = arch_fetch_arg_init_32(ctx, type, proc, ret_info);
751a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	else
752a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		ret = arch_fetch_arg_init_64(ctx, type, proc, ret_info);
753a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (ret == NULL)
754a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		goto fail;
755a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	return ret;
756a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
757a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
758a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastruct fetch_context *
759929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataarch_fetch_arg_clone(struct process *proc, struct fetch_context *context)
760a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
761a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	struct fetch_context *ret = malloc(sizeof(*ret));
762a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (ret == NULL)
763a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return NULL;
764a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	return memcpy(ret, context, sizeof(*ret));
765a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
766a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
767a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatastatic int
768a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataarch_fetch_pool_arg_next(struct fetch_context *context, enum tof type,
769929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata			 struct process *proc, struct arg_type_info *info,
770a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			 struct value *valuep, enum reg_pool pool)
771a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
772a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	enum arg_class classes[2];
773a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	size_t sz, sz1;
774a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	ssize_t i;
775a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	ssize_t nclasses = classify_argument(proc, context, info, valuep,
776a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata					     classes, &sz);
777a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (nclasses == -1)
778a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return -1;
779a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (value_reserve(valuep, sz) == NULL)
780a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return -1;
781a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
782a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	/* If there are no registers available for any eightbyte of an
783a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 * argument, the whole argument is passed on the stack.  If
784a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 * registers have already been assigned for some eightbytes of
785a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	 * such an argument, the assignments get reverted.  */
786a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	struct fetch_context tmp_context = *context;
787a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	int revert;
788a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (nclasses == 1) {
789a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		revert = allocate_class(classes[0], &tmp_context,
790a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata					valuep, sz, 0, pool) != classes[0];
791a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	} else {
792a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		revert = 0;
793a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		for (i = 0; i < nclasses; ++i) {
794a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			sz1 = (size_t)(8 * (i + 1)) > sz ? sz - 8 * i : 8;
795a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			if (allocate_class(classes[i], &tmp_context, valuep,
796a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata					   sz1, 8 * i, pool) != classes[i])
797a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata				revert = 1;
798a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		}
799a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
800a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
801a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (nclasses > 1 && revert)
802a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		allocate_class(CLASS_MEMORY, context, valuep, sz, 0, pool);
803a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	else
804a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		*context = tmp_context; /* Commit.  */
805a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
806a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	return 0;
807a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
808a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
809a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataint
810a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataarch_fetch_fun_retval(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	assert(type != LT_TOF_FUNCTION
815a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	       && type != LT_TOF_SYSCALL);
816a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (value_reserve(valuep, 8 * context->u.x86_64.num_ret_classes) == NULL
817a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	    || fetch_register_banks(proc, context,
818a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata				    type == LT_TOF_FUNCTIONR) < 0)
819a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return -1;
820a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
821a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (context->u.x86_64.num_ret_classes == 1
822a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	    && context->u.x86_64.ret_classes[0] == CLASS_MEMORY)
823a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		pass_by_reference(valuep, context->u.x86_64.ret_classes);
824a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
825a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	size_t sz = type_sizeof(proc, valuep->type);
826a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (sz == (size_t)-1)
827a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return -1;
828a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
829a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	ssize_t i;
830a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	size_t sz1 = context->u.x86_64.num_ret_classes == 1 ? sz : 8;
831a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	for (i = 0; i < context->u.x86_64.num_ret_classes; ++i) {
832a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		enum arg_class cls
833a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata			= allocate_class(context->u.x86_64.ret_classes[i],
834a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata					 context, valuep, sz1,
835a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata					 8 * i, POOL_RETVAL);
836a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		assert(cls == context->u.x86_64.ret_classes[i]);
837a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
838a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	return 0;
839a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
840a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
841a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataint
842a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataarch_fetch_arg_next(struct fetch_context *context, enum tof type,
843929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata		    struct process *proc, struct arg_type_info *info,
844a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		    struct value *valuep)
845a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
846a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (proc->e_machine == EM_386)
847a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return arch_fetch_arg_next_32(context, type, proc,
848a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata					      info, valuep);
849a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
850a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	switch (type) {
851a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case LT_TOF_FUNCTION:
852a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case LT_TOF_FUNCTIONR:
853a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return arch_fetch_pool_arg_next(context, type, proc,
854a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata						info, valuep, POOL_FUNCALL);
855a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
856a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case LT_TOF_SYSCALL:
857a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	case LT_TOF_SYSCALLR:
858a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return arch_fetch_pool_arg_next(context, type, proc,
859a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata						info, valuep, POOL_SYSCALL);
860a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	}
861a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
862a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	abort();
863a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
864a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
865a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataint
866a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataarch_fetch_retval(struct fetch_context *context, enum tof type,
867929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata		  struct process *proc, struct arg_type_info *info,
868a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		  struct value *valuep)
869a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
870a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (proc->e_machine == EM_386)
871a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		return arch_fetch_retval_32(context, type, proc, info, valuep);
872a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
873a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	return arch_fetch_fun_retval(context, type, proc, info, valuep);
874a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
875a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata
876a7ec2d840a68bf103aacd240555406955c397ecfPetr Machatavoid
877a7ec2d840a68bf103aacd240555406955c397ecfPetr Machataarch_fetch_arg_done(struct fetch_context *context)
878a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata{
879a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata	if (context != NULL)
880a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata		free(context);
881a7ec2d840a68bf103aacd240555406955c397ecfPetr Machata}
882