fetch.c revision 929bd57ca202fd2f2e8485ebf65d683e664f67b5
1ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata/*
2ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata * This file is part of ltrace.
3ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata * Copyright (C) 2012 Petr Machata, Red Hat Inc.
4ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata *
5ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata * This program is free software; you can redistribute it and/or
6ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata * modify it under the terms of the GNU General Public License as
7ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata * published by the Free Software Foundation; either version 2 of the
8ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata * License, or (at your option) any later version.
9ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata *
10ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata * This program is distributed in the hope that it will be useful, but
11ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of
12ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata * General Public License for more details.
14ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata *
15ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata * You should have received a copy of the GNU General Public License
16ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata * along with this program; if not, write to the Free Software
17ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata * 02110-1301 USA
19ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata */
20ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
21ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata#include <asm/ptrace.h>
22ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata#include <sys/ptrace.h>
23ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata#include <sys/ucontext.h>
24ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata#include <assert.h>
25ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata#include <errno.h>
26ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata#include <stdio.h>
27ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata#include <stdlib.h>
28ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata#include <string.h>
29ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
30ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata#include "backend.h"
31ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata#include "fetch.h"
32ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata#include "type.h"
33ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata#include "proc.h"
34ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata#include "value.h"
35ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
36ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machatastruct fetch_context {
37ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	struct user_regs_struct regs;
38ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	arch_addr_t stack_pointer;
39ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	int greg;
40ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	int freg;
41ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata};
42ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
43ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machatastatic int
4482b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machatas390x(struct fetch_context *ctx)
4582b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata{
468d30fd9f26ccd15f0fa27e09d1fd99deddb17d36Petr Machata	/* +--------+--------+--------+
478d30fd9f26ccd15f0fa27e09d1fd99deddb17d36Petr Machata	 * | PSW.31 | PSW.32 | mode   |
488d30fd9f26ccd15f0fa27e09d1fd99deddb17d36Petr Machata	 * +--------+--------+--------+
498d30fd9f26ccd15f0fa27e09d1fd99deddb17d36Petr Machata	 * | 0      | 0      | 24-bit | Not supported in Linux
508d30fd9f26ccd15f0fa27e09d1fd99deddb17d36Petr Machata	 * | 0      | 1      | 31-bit | s390 compatible mode
518d30fd9f26ccd15f0fa27e09d1fd99deddb17d36Petr Machata	 * | 1      | 1      | 64-bit | z/Architecture, "s390x"
528d30fd9f26ccd15f0fa27e09d1fd99deddb17d36Petr Machata	 * +--------+--------+--------+
538d30fd9f26ccd15f0fa27e09d1fd99deddb17d36Petr Machata	 * (Note: The leftmost bit is PSW.0, rightmost PSW.63.)
548d30fd9f26ccd15f0fa27e09d1fd99deddb17d36Petr Machata	 */
558d30fd9f26ccd15f0fa27e09d1fd99deddb17d36Petr Machata
5682b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata#ifdef __s390x__
5782b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata	if ((ctx->regs.psw.mask & 0x180000000UL) == 0x180000000UL)
5882b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata		return 1;
5982b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata#endif
6082b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata	return 0;
6182b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata}
6282b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata
6382b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machatastatic int
64929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatafetch_register_banks(struct process *proc, struct fetch_context *ctx)
65ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata{
66ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	ptrace_area parea;
67ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	parea.len = sizeof(ctx->regs);
68ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	parea.process_addr = (uintptr_t)&ctx->regs;
69ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	parea.kernel_addr = 0;
70ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	if (ptrace(PTRACE_PEEKUSR_AREA, proc->pid, &parea, NULL) < 0) {
71ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		fprintf(stderr, "fetch_register_banks GPR: %s\n",
72ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata			strerror(errno));
73ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		return -1;
74ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	}
75ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	return 0;
76ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata}
77ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
78ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machatastatic int
79929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatafetch_context_init(struct process *proc, struct fetch_context *context)
80ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata{
81ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	context->greg = 2;
82ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	context->freg = 0;
83ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	return fetch_register_banks(proc, context);
84ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata}
85ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
86ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machatastruct fetch_context *
87929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataarch_fetch_arg_init(enum tof type, struct process *proc,
88ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		    struct arg_type_info *ret_info)
89ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata{
90ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	struct fetch_context *context = malloc(sizeof(*context));
91ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	if (context == NULL
92ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	    || fetch_context_init(proc, context) < 0) {
93ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		fprintf(stderr, "arch_fetch_arg_init: %s\n",
94ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata			strerror(errno));
95ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		free(context);
96ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		return NULL;
97ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	}
98ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
9982b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata	context->stack_pointer = get_stack_pointer(proc)
10082b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata		+ (s390x(context) ? 160 : 96);
101ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	if (ret_info->type == ARGTYPE_STRUCT)
102ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		++context->greg;
103ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
104ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	return context;
105ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata}
106ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
107ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machatastruct fetch_context *
108929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataarch_fetch_arg_clone(struct process *proc,
109ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		     struct fetch_context *context)
110ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata{
111ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	struct fetch_context *clone = malloc(sizeof(*context));
112ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	if (clone == NULL)
113ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		return NULL;
114ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	*clone = *context;
115ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	return clone;
116ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata}
117ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
118ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machatastatic int
119929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataallocate_stack_slot(struct fetch_context *ctx, struct process *proc,
1200b926f68098c4dd0df922ba2c6214ed902cd4cd6Petr Machata		    struct arg_type_info *info, struct value *valuep,
1210b926f68098c4dd0df922ba2c6214ed902cd4cd6Petr Machata		    size_t sz)
122ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata{
123df59c75ee9fa70343c9af929403cd3d371443714Petr Machata	/* Note: here we shouldn't see large composite types, those
12482b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata	 * are passed by reference, which is handled below.  Here we
125df59c75ee9fa70343c9af929403cd3d371443714Petr Machata	 * only deal with integers, floats, small structs, etc.  */
12682b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata
12782b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata	size_t a;
12882b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata	if (s390x(ctx)) {
12982b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata		assert(sz <= 8);
130ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		a = 8;
13182b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata	} else {
13282b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata		/* Note: double is 8 bytes.  */
13382b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata		assert(sz <= 8);
13482b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata		a = 4;
13582b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata	}
136ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
13782b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata	size_t off = sz < a ? a - sz : 0;
1380ffa9f3f82febbcd475318ac282c456adb76c73cPetr Machata	value_in_inferior(valuep, ctx->stack_pointer + off);
139ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
14082b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata	ctx->stack_pointer += sz > a ? sz : a;
141ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	return 0;
142ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata}
143ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
144ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machatastatic void
145ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machatacopy_gpr(struct fetch_context *ctx, struct value *valuep, int regno)
146ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata{
147ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	value_set_word(valuep, ctx->regs.gprs[regno]);
148ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata}
149ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
150ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machatastatic int
151929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataallocate_gpr(struct fetch_context *ctx, struct process *proc,
1520b926f68098c4dd0df922ba2c6214ed902cd4cd6Petr Machata	     struct arg_type_info *info, struct value *valuep,
1530b926f68098c4dd0df922ba2c6214ed902cd4cd6Petr Machata	     size_t sz)
154ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata{
155ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	if (ctx->greg > 6)
1560b926f68098c4dd0df922ba2c6214ed902cd4cd6Petr Machata		return allocate_stack_slot(ctx, proc, info, valuep, sz);
157ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
158ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	copy_gpr(ctx, valuep, ctx->greg++);
159ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	return 0;
160ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata}
161ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
162ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machatastatic int
163929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataallocate_gpr_pair(struct fetch_context *ctx, struct process *proc,
164df59c75ee9fa70343c9af929403cd3d371443714Petr Machata		  struct arg_type_info *info, struct value *valuep,
165df59c75ee9fa70343c9af929403cd3d371443714Petr Machata		  size_t sz)
166df59c75ee9fa70343c9af929403cd3d371443714Petr Machata{
167df59c75ee9fa70343c9af929403cd3d371443714Petr Machata	assert(!s390x(ctx));
168df59c75ee9fa70343c9af929403cd3d371443714Petr Machata	assert(sz <= 8);
169df59c75ee9fa70343c9af929403cd3d371443714Petr Machata
170df59c75ee9fa70343c9af929403cd3d371443714Petr Machata	if (ctx->greg > 5) {
171df59c75ee9fa70343c9af929403cd3d371443714Petr Machata		ctx->greg = 7;
172df59c75ee9fa70343c9af929403cd3d371443714Petr Machata		return allocate_stack_slot(ctx, proc, info, valuep, sz);
173df59c75ee9fa70343c9af929403cd3d371443714Petr Machata	}
174df59c75ee9fa70343c9af929403cd3d371443714Petr Machata
175df59c75ee9fa70343c9af929403cd3d371443714Petr Machata	if (value_reserve(valuep, sz) == NULL)
176df59c75ee9fa70343c9af929403cd3d371443714Petr Machata		return -1;
177df59c75ee9fa70343c9af929403cd3d371443714Petr Machata
178df59c75ee9fa70343c9af929403cd3d371443714Petr Machata	unsigned char *ptr = value_get_raw_data(valuep);
179df59c75ee9fa70343c9af929403cd3d371443714Petr Machata	union {
180df59c75ee9fa70343c9af929403cd3d371443714Petr Machata		struct {
181df59c75ee9fa70343c9af929403cd3d371443714Petr Machata			uint32_t a;
182df59c75ee9fa70343c9af929403cd3d371443714Petr Machata			uint32_t b;
183df59c75ee9fa70343c9af929403cd3d371443714Petr Machata		};
184df59c75ee9fa70343c9af929403cd3d371443714Petr Machata		unsigned char buf[8];
185df59c75ee9fa70343c9af929403cd3d371443714Petr Machata	} u;
186df59c75ee9fa70343c9af929403cd3d371443714Petr Machata	u.a = ctx->regs.gprs[ctx->greg++];
187df59c75ee9fa70343c9af929403cd3d371443714Petr Machata	u.b = ctx->regs.gprs[ctx->greg++];
188df59c75ee9fa70343c9af929403cd3d371443714Petr Machata	memcpy(ptr, u.buf, sz);
189df59c75ee9fa70343c9af929403cd3d371443714Petr Machata
190df59c75ee9fa70343c9af929403cd3d371443714Petr Machata	return 0;
191df59c75ee9fa70343c9af929403cd3d371443714Petr Machata}
192df59c75ee9fa70343c9af929403cd3d371443714Petr Machata
193df59c75ee9fa70343c9af929403cd3d371443714Petr Machatastatic int
194929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataallocate_fpr(struct fetch_context *ctx, struct process *proc,
1950b926f68098c4dd0df922ba2c6214ed902cd4cd6Petr Machata	     struct arg_type_info *info, struct value *valuep,
1960b926f68098c4dd0df922ba2c6214ed902cd4cd6Petr Machata	     size_t sz)
197ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata{
19882b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata	int pool = s390x(ctx) ? 6 : 2;
19982b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata
20082b1977bfdc0c31be26454257db28a1cb497fbf2Petr Machata	if (ctx->freg > pool)
2010b926f68098c4dd0df922ba2c6214ed902cd4cd6Petr Machata		return allocate_stack_slot(ctx, proc, info, valuep, sz);
202ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
203ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	if (value_reserve(valuep, sz) == NULL)
204ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		return -1;
205ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
206ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	memcpy(value_get_raw_data(valuep),
207ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	       &ctx->regs.fp_regs.fprs[ctx->freg], sz);
208ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	ctx->freg += 2;
209ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
210ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	return 0;
211ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata}
212ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
213ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machataint
214ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machataarch_fetch_arg_next(struct fetch_context *ctx, enum tof type,
215929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata		    struct process *proc,
216ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		    struct arg_type_info *info, struct value *valuep)
217ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata{
2180b926f68098c4dd0df922ba2c6214ed902cd4cd6Petr Machata	size_t sz = type_sizeof(proc, info);
2190b926f68098c4dd0df922ba2c6214ed902cd4cd6Petr Machata	if (sz == (size_t)-1)
2200b926f68098c4dd0df922ba2c6214ed902cd4cd6Petr Machata		return -1;
2210b926f68098c4dd0df922ba2c6214ed902cd4cd6Petr Machata
222ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	switch (info->type) {
223ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	case ARGTYPE_VOID:
224ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		value_set_word(valuep, 0);
225ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		return 0;
226ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
227ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	case ARGTYPE_STRUCT:
228fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata		if (type_get_fp_equivalent(info) != NULL)
229ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata			/* fall through */
230ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	case ARGTYPE_FLOAT:
231ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	case ARGTYPE_DOUBLE:
2320b926f68098c4dd0df922ba2c6214ed902cd4cd6Petr Machata			return allocate_fpr(ctx, proc, info, valuep, sz);
233ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
23412d64f8bbae6245146900e8ee2292d854a22f26dPetr Machata		/* Structures<4 bytes on s390 and structures<8 bytes
23512d64f8bbae6245146900e8ee2292d854a22f26dPetr Machata		 * on s390x are passed in register.  On s390, long
23612d64f8bbae6245146900e8ee2292d854a22f26dPetr Machata		 * long and structures<8 bytes are passed in two
23712d64f8bbae6245146900e8ee2292d854a22f26dPetr Machata		 * consecutive registers (if two are available).  */
23812d64f8bbae6245146900e8ee2292d854a22f26dPetr Machata
239df59c75ee9fa70343c9af929403cd3d371443714Petr Machata		if (sz <= (s390x(ctx) ? 8 : 4))
2400b926f68098c4dd0df922ba2c6214ed902cd4cd6Petr Machata			return allocate_gpr(ctx, proc, info, valuep, sz);
241df59c75ee9fa70343c9af929403cd3d371443714Petr Machata		else if (sz <= 8)
242df59c75ee9fa70343c9af929403cd3d371443714Petr Machata			return allocate_gpr_pair(ctx, proc, info, valuep, sz);
24312d64f8bbae6245146900e8ee2292d854a22f26dPetr Machata
244ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		/* fall through */
245ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
246ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	case ARGTYPE_ARRAY:
247ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		if (value_pass_by_reference(valuep) < 0)
248ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata			return -1;
249ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		/* fall through */
250ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
251ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	case ARGTYPE_INT:
252ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	case ARGTYPE_UINT:
253ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	case ARGTYPE_LONG:
254ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	case ARGTYPE_ULONG:
255ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	case ARGTYPE_CHAR:
256ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	case ARGTYPE_SHORT:
257ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	case ARGTYPE_USHORT:
258ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	case ARGTYPE_POINTER:
2590b926f68098c4dd0df922ba2c6214ed902cd4cd6Petr Machata		return allocate_gpr(ctx, proc, info, valuep, sz);
2605b5c256d0e9076e745908a43acc46353265a5608Edgar E. Iglesias
2615b5c256d0e9076e745908a43acc46353265a5608Edgar E. Iglesias	default:
2625b5c256d0e9076e745908a43acc46353265a5608Edgar E. Iglesias		assert(info->type != info->type);
2635b5c256d0e9076e745908a43acc46353265a5608Edgar E. Iglesias		abort();
264ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	}
265ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	return -1;
266ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata}
267ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
268ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machataint
269ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machataarch_fetch_retval(struct fetch_context *ctx, enum tof type,
270929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata		  struct process *proc, struct arg_type_info *info,
271ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		  struct value *valuep)
272ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata{
273ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	if (info->type == ARGTYPE_STRUCT) {
274ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		if (value_pass_by_reference(valuep) < 0)
275ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata			return -1;
276ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		copy_gpr(ctx, valuep, 2);
277ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		return 0;
278ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	}
279ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
280ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	if (fetch_context_init(proc, ctx) < 0)
281ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata		return -1;
282ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	return arch_fetch_arg_next(ctx, type, proc, info, valuep);
283ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata}
284ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata
285ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machatavoid
286ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machataarch_fetch_arg_done(struct fetch_context *context)
287ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata{
288ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata	free(context);
289ecb2e82fe81684fc10876db6b73de8cefad06d9aPetr Machata}
290