blob: 79d3b4a38765105da67779f7b5206ae501633db6 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $Id$
34 */
35
36#include "defs.h"
37
38#include <signal.h>
39#include <time.h>
40#include <errno.h>
41#include <sys/user.h>
42#include <sys/syscall.h>
43#include <sys/param.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000044
Wichert Akkerman15dea971999-10-06 13:06:34 +000045#ifdef HAVE_SYS_REG_H
Roland McGratheb9e2e82009-06-02 16:49:22 -070046#include <sys/reg.h>
47#ifndef PTRACE_PEEKUSR
48# define PTRACE_PEEKUSR PTRACE_PEEKUSER
49#endif
Wichert Akkermanfaf72222000-02-19 23:59:03 +000050#elif defined(HAVE_LINUX_PTRACE_H)
Roland McGratheb9e2e82009-06-02 16:49:22 -070051#undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000052# ifdef HAVE_STRUCT_IA64_FPREG
53# define ia64_fpreg XXX_ia64_fpreg
54# endif
55# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
56# define pt_all_user_regs XXX_pt_all_user_regs
57# endif
Roland McGratheb9e2e82009-06-02 16:49:22 -070058#include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000059# undef ia64_fpreg
60# undef pt_all_user_regs
Wichert Akkerman15dea971999-10-06 13:06:34 +000061#endif
62
Roland McGrath6d1a65c2004-07-12 07:44:08 +000063#if defined (LINUX) && defined (SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +000064# undef PTRACE_GETREGS
65# define PTRACE_GETREGS PTRACE_GETREGS64
66# undef PTRACE_SETREGS
67# define PTRACE_SETREGS PTRACE_SETREGS64
68#endif /* LINUX && SPARC64 */
69
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000070#if defined(LINUX) && defined(IA64)
71# include <asm/ptrace_offsets.h>
72# include <asm/rse.h>
73#endif
74
Pavel Machekd8ae7e32000-02-01 17:17:25 +000075#define NR_SYSCALL_BASE 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000076#ifdef LINUX
77#ifndef ERESTARTSYS
78#define ERESTARTSYS 512
79#endif
80#ifndef ERESTARTNOINTR
81#define ERESTARTNOINTR 513
82#endif
83#ifndef ERESTARTNOHAND
84#define ERESTARTNOHAND 514 /* restart if no handler.. */
85#endif
86#ifndef ENOIOCTLCMD
87#define ENOIOCTLCMD 515 /* No ioctl command */
88#endif
Roland McGrath9c555e72003-07-09 09:47:59 +000089#ifndef ERESTART_RESTARTBLOCK
90#define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
91#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000092#ifndef NSIG
93#define NSIG 32
94#endif
95#ifdef ARM
96#undef NSIG
97#define NSIG 32
Pavel Machekd8ae7e32000-02-01 17:17:25 +000098#undef NR_SYSCALL_BASE
99#define NR_SYSCALL_BASE __NR_SYSCALL_BASE
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000100#endif
101#endif /* LINUX */
102
103#include "syscall.h"
104
105/* Define these shorthand notations to simplify the syscallent files. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000106#define TD TRACE_DESC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000107#define TF TRACE_FILE
108#define TI TRACE_IPC
109#define TN TRACE_NETWORK
110#define TP TRACE_PROCESS
111#define TS TRACE_SIGNAL
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000112#define NF SYSCALL_NEVER_FAILS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000113
Roland McGrathee36ce12004-09-04 03:53:10 +0000114static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000115#include "syscallent.h"
116};
Roland McGrathee36ce12004-09-04 03:53:10 +0000117static const int nsyscalls0 = sizeof sysent0 / sizeof sysent0[0];
Roland McGrath138c6a32006-01-12 09:50:49 +0000118int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000119
120#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000121static const struct sysent sysent1[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122#include "syscallent1.h"
123};
Roland McGrathee36ce12004-09-04 03:53:10 +0000124static const int nsyscalls1 = sizeof sysent1 / sizeof sysent1[0];
Roland McGrath138c6a32006-01-12 09:50:49 +0000125int qual_flags1[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000126#endif /* SUPPORTED_PERSONALITIES >= 2 */
127
128#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000129static const struct sysent sysent2[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130#include "syscallent2.h"
131};
Roland McGrathee36ce12004-09-04 03:53:10 +0000132static const int nsyscalls2 = sizeof sysent2 / sizeof sysent2[0];
Roland McGrath138c6a32006-01-12 09:50:49 +0000133int qual_flags2[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000134#endif /* SUPPORTED_PERSONALITIES >= 3 */
135
Roland McGrathee36ce12004-09-04 03:53:10 +0000136const struct sysent *sysent;
Roland McGrath138c6a32006-01-12 09:50:49 +0000137int *qual_flags;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000138int nsyscalls;
139
140/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000141#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142#undef TF
143#undef TI
144#undef TN
145#undef TP
146#undef TS
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000147#undef NF
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000148
Roland McGrathee36ce12004-09-04 03:53:10 +0000149static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000150#include "errnoent.h"
151};
Roland McGrathee36ce12004-09-04 03:53:10 +0000152static const int nerrnos0 = sizeof errnoent0 / sizeof errnoent0[0];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000153
154#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000155static const char *const errnoent1[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000156#include "errnoent1.h"
157};
Roland McGrathee36ce12004-09-04 03:53:10 +0000158static const int nerrnos1 = sizeof errnoent1 / sizeof errnoent1[0];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000159#endif /* SUPPORTED_PERSONALITIES >= 2 */
160
161#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000162static const char *const errnoent2[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000163#include "errnoent2.h"
164};
Roland McGrathee36ce12004-09-04 03:53:10 +0000165static const int nerrnos2 = sizeof errnoent2 / sizeof errnoent2[0];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000166#endif /* SUPPORTED_PERSONALITIES >= 3 */
167
Roland McGrathee36ce12004-09-04 03:53:10 +0000168const char *const *errnoent;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000169int nerrnos;
170
171int current_personality;
172
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000173#ifndef PERSONALITY0_WORDSIZE
174# define PERSONALITY0_WORDSIZE sizeof(long)
175#endif
176const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
177 PERSONALITY0_WORDSIZE,
178#if SUPPORTED_PERSONALITIES > 1
179 PERSONALITY1_WORDSIZE,
180#endif
181#if SUPPORTED_PERSONALITIES > 2
182 PERSONALITY2_WORDSIZE,
183#endif
184};;
185
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000186int
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000187set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000188{
189 switch (personality) {
190 case 0:
191 errnoent = errnoent0;
192 nerrnos = nerrnos0;
193 sysent = sysent0;
194 nsyscalls = nsyscalls0;
195 ioctlent = ioctlent0;
196 nioctlents = nioctlents0;
197 signalent = signalent0;
198 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000199 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000200 break;
201
202#if SUPPORTED_PERSONALITIES >= 2
203 case 1:
204 errnoent = errnoent1;
205 nerrnos = nerrnos1;
206 sysent = sysent1;
207 nsyscalls = nsyscalls1;
208 ioctlent = ioctlent1;
209 nioctlents = nioctlents1;
210 signalent = signalent1;
211 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000212 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000213 break;
214#endif /* SUPPORTED_PERSONALITIES >= 2 */
215
216#if SUPPORTED_PERSONALITIES >= 3
217 case 2:
218 errnoent = errnoent2;
219 nerrnos = nerrnos2;
220 sysent = sysent2;
221 nsyscalls = nsyscalls2;
222 ioctlent = ioctlent2;
223 nioctlents = nioctlents2;
224 signalent = signalent2;
225 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000226 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000227 break;
228#endif /* SUPPORTED_PERSONALITIES >= 3 */
229
230 default:
231 return -1;
232 }
233
234 current_personality = personality;
235 return 0;
236}
237
Roland McGrathe10e62a2004-09-04 04:20:43 +0000238
Roland McGrath9797ceb2002-12-30 10:23:00 +0000239static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000240
Roland McGrathe10e62a2004-09-04 04:20:43 +0000241static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000242 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000243 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000244 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000245 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000246} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000247 { QUAL_TRACE, "trace", qual_syscall, "system call" },
248 { QUAL_TRACE, "t", qual_syscall, "system call" },
249 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
250 { QUAL_ABBREV, "a", qual_syscall, "system call" },
251 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
252 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
253 { QUAL_RAW, "raw", qual_syscall, "system call" },
254 { QUAL_RAW, "x", qual_syscall, "system call" },
255 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
256 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
257 { QUAL_SIGNAL, "s", qual_signal, "signal" },
258 { QUAL_FAULT, "fault", qual_fault, "fault" },
259 { QUAL_FAULT, "faults", qual_fault, "fault" },
260 { QUAL_FAULT, "m", qual_fault, "fault" },
261 { QUAL_READ, "read", qual_desc, "descriptor" },
262 { QUAL_READ, "reads", qual_desc, "descriptor" },
263 { QUAL_READ, "r", qual_desc, "descriptor" },
264 { QUAL_WRITE, "write", qual_desc, "descriptor" },
265 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
266 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000267 { 0, NULL, NULL, NULL },
268};
269
Roland McGrath9797ceb2002-12-30 10:23:00 +0000270static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000271qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000272{
Roland McGrath138c6a32006-01-12 09:50:49 +0000273 if (pers == 0 || pers < 0) {
274 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000275 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000276 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000277 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000278 }
279
280#if SUPPORTED_PERSONALITIES >= 2
281 if (pers == 1 || pers < 0) {
282 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000283 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000284 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000285 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000286 }
287#endif /* SUPPORTED_PERSONALITIES >= 2 */
288
289#if SUPPORTED_PERSONALITIES >= 3
290 if (pers == 2 || pers < 0) {
291 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000292 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000293 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000294 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000295 }
296#endif /* SUPPORTED_PERSONALITIES >= 3 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000297}
298
299static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000300qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000301{
302 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000303 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000304
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000305 if (isdigit((unsigned char)*s)) {
306 int i = atoi(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000307 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000308 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000309 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000310 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000311 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000312 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000313 if (strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000314 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000315 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000316 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000317
318#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000319 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000320 if (strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000321 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000322 rc = 0;
323 }
324#endif /* SUPPORTED_PERSONALITIES >= 2 */
325
326#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000327 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000328 if (strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000329 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000330 rc = 0;
331 }
332#endif /* SUPPORTED_PERSONALITIES >= 3 */
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000333
Roland McGrathfe6b3522005-02-02 04:40:11 +0000334 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000335}
336
337static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000338qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000339{
340 int i;
341 char buf[32];
342
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000343 if (isdigit((unsigned char)*s)) {
344 int signo = atoi(s);
345 if (signo < 0 || signo >= MAX_QUALS)
346 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000347 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000348 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000349 }
Roland McGrathd62b6712004-03-02 06:52:01 +0000350 if (strlen(s) >= sizeof buf)
Roland McGrathfe6b3522005-02-02 04:40:11 +0000351 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000352 strcpy(buf, s);
353 s = buf;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000354 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000355 s += 3;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000356 for (i = 0; i <= NSIG; i++)
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000357 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000358 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000359 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000360 }
Roland McGrath76421df2005-02-02 03:51:18 +0000361 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000362}
363
364static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000365qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000366{
367 return -1;
368}
369
370static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000371qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000372{
Roland McGrath48a035f2006-01-12 09:45:56 +0000373 if (isdigit((unsigned char)*s)) {
Roland McGrathfe6b3522005-02-02 04:40:11 +0000374 int desc = atoi(s);
375 if (desc < 0 || desc >= MAX_QUALS)
376 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000377 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000378 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000379 }
380 return -1;
381}
382
383static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000384lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000385{
386 if (strcmp(s, "file") == 0)
387 return TRACE_FILE;
388 if (strcmp(s, "ipc") == 0)
389 return TRACE_IPC;
390 if (strcmp(s, "network") == 0)
391 return TRACE_NETWORK;
392 if (strcmp(s, "process") == 0)
393 return TRACE_PROCESS;
394 if (strcmp(s, "signal") == 0)
395 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000396 if (strcmp(s, "desc") == 0)
397 return TRACE_DESC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000398 return -1;
399}
400
401void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000402qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000403{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000404 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000405 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000406 char *copy;
407 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000408 int i, n;
409
410 opt = &qual_options[0];
411 for (i = 0; (p = qual_options[i].option_name); i++) {
412 n = strlen(p);
413 if (strncmp(s, p, n) == 0 && s[n] == '=') {
414 opt = &qual_options[i];
415 s += n + 1;
416 break;
417 }
418 }
419 not = 0;
420 if (*s == '!') {
421 not = 1;
422 s++;
423 }
424 if (strcmp(s, "none") == 0) {
425 not = 1 - not;
426 s = "all";
427 }
428 if (strcmp(s, "all") == 0) {
429 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000430 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000431 }
432 return;
433 }
434 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000435 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000436 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000437 if (!(copy = strdup(s))) {
438 fprintf(stderr, "out of memory\n");
439 exit(1);
440 }
441 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000442 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000443 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000444 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000445 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000446
447#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000448 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000449 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000450 qualify_one(i, opt->bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000451#endif /* SUPPORTED_PERSONALITIES >= 2 */
452
453#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000454 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000455 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000456 qualify_one(i, opt->bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000457#endif /* SUPPORTED_PERSONALITIES >= 3 */
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000458
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000459 continue;
460 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000461 if (opt->qualify(p, opt->bitflag, not)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000462 fprintf(stderr, "strace: invalid %s `%s'\n",
463 opt->argument_name, p);
464 exit(1);
465 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000466 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000467 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000468 return;
469}
470
471static void
Dmitry V. Levin65c1a812011-02-09 00:39:47 +0000472dumpio(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000473{
474 if (syserror(tcp))
475 return;
476 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
477 return;
Dmitry V. Levin65c1a812011-02-09 00:39:47 +0000478 if (tcp->scno < 0 || tcp->scno >= nsyscalls)
479 return;
480 if (sysent[tcp->scno].sys_func == printargs)
481 return;
482 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
483 if (sysent[tcp->scno].sys_func == sys_read ||
484 sysent[tcp->scno].sys_func == sys_pread ||
485 sysent[tcp->scno].sys_func == sys_pread64 ||
486 sysent[tcp->scno].sys_func == sys_recv ||
487 sysent[tcp->scno].sys_func == sys_recvfrom)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000488 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
Dmitry V. Levin65c1a812011-02-09 00:39:47 +0000489 else if (sysent[tcp->scno].sys_func == sys_readv)
490 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
491 return;
492 }
493 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
494 if (sysent[tcp->scno].sys_func == sys_write ||
495 sysent[tcp->scno].sys_func == sys_pwrite ||
496 sysent[tcp->scno].sys_func == sys_pwrite64 ||
497 sysent[tcp->scno].sys_func == sys_send ||
498 sysent[tcp->scno].sys_func == sys_sendto)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000499 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
Dmitry V. Levin65c1a812011-02-09 00:39:47 +0000500 else if (sysent[tcp->scno].sys_func == sys_writev)
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000501 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
Dmitry V. Levin65c1a812011-02-09 00:39:47 +0000502 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000503 }
504}
505
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000506#ifndef FREEBSD
Wichert Akkerman8829a551999-06-11 13:18:40 +0000507enum subcall_style { shift_style, deref_style, mask_style, door_style };
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000508#else /* FREEBSD */
509enum subcall_style { shift_style, deref_style, mask_style, door_style, table_style };
510
511struct subcall {
512 int call;
513 int nsubcalls;
514 int subcalls[5];
515};
516
Roland McGratha4d48532005-06-08 20:45:28 +0000517static const struct subcall subcalls_table[] = {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000518 { SYS_shmsys, 5, { SYS_shmat, SYS_shmctl, SYS_shmdt, SYS_shmget, SYS_shmctl } },
John Hughes61eeb552001-03-06 15:51:53 +0000519#ifdef SYS_semconfig
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000520 { SYS_semsys, 4, { SYS___semctl, SYS_semget, SYS_semop, SYS_semconfig } },
John Hughes61eeb552001-03-06 15:51:53 +0000521#else
522 { SYS_semsys, 3, { SYS___semctl, SYS_semget, SYS_semop } },
523#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000524 { SYS_msgsys, 4, { SYS_msgctl, SYS_msgget, SYS_msgsnd, SYS_msgrcv } },
525};
526#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000527
Denys Vlasenko8ba1cd72008-12-30 17:50:46 +0000528#if !(defined(LINUX) && ( defined(ALPHA) || defined(MIPS) || defined(__ARM_EABI__) ))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000529
Roland McGratha4d48532005-06-08 20:45:28 +0000530static void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000531decode_subcall(tcp, subcall, nsubcalls, style)
532struct tcb *tcp;
533int subcall;
534int nsubcalls;
535enum subcall_style style;
536{
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000537 unsigned long addr, mask;
Michal Ludvig10a88d02002-10-07 14:31:00 +0000538 int i;
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000539 int size = personality_wordsize[current_personality];
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000540
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000541 switch (style) {
542 case shift_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000543 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
544 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000545 tcp->scno = subcall + tcp->u_arg[0];
546 if (sysent[tcp->scno].nargs != -1)
547 tcp->u_nargs = sysent[tcp->scno].nargs;
548 else
549 tcp->u_nargs--;
550 for (i = 0; i < tcp->u_nargs; i++)
551 tcp->u_arg[i] = tcp->u_arg[i + 1];
552 break;
553 case deref_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000554 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
555 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000556 tcp->scno = subcall + tcp->u_arg[0];
557 addr = tcp->u_arg[1];
558 for (i = 0; i < sysent[tcp->scno].nargs; i++) {
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000559 if (size == sizeof(int)) {
560 unsigned int arg;
561 if (umove(tcp, addr, &arg) < 0)
562 arg = 0;
563 tcp->u_arg[i] = arg;
564 }
565 else if (size == sizeof(long)) {
566 unsigned long arg;
567 if (umove(tcp, addr, &arg) < 0)
568 arg = 0;
569 tcp->u_arg[i] = arg;
570 }
571 else
572 abort();
573 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000574 }
575 tcp->u_nargs = sysent[tcp->scno].nargs;
576 break;
577 case mask_style:
578 mask = (tcp->u_arg[0] >> 8) & 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000579 for (i = 0; mask; i++)
580 mask >>= 1;
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000581 if (i >= nsubcalls)
582 return;
583 tcp->u_arg[0] &= 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000584 tcp->scno = subcall + i;
585 if (sysent[tcp->scno].nargs != -1)
586 tcp->u_nargs = sysent[tcp->scno].nargs;
587 break;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000588 case door_style:
589 /*
590 * Oh, yuck. The call code is the *sixth* argument.
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000591 * (don't you mean the *last* argument? - JH)
Wichert Akkerman8829a551999-06-11 13:18:40 +0000592 */
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000593 if (tcp->u_arg[5] < 0 || tcp->u_arg[5] >= nsubcalls)
594 return;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000595 tcp->scno = subcall + tcp->u_arg[5];
596 if (sysent[tcp->scno].nargs != -1)
597 tcp->u_nargs = sysent[tcp->scno].nargs;
598 else
599 tcp->u_nargs--;
600 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000601#ifdef FREEBSD
602 case table_style:
603 for (i = 0; i < sizeof(subcalls_table) / sizeof(struct subcall); i++)
604 if (subcalls_table[i].call == tcp->scno) break;
605 if (i < sizeof(subcalls_table) / sizeof(struct subcall) &&
606 tcp->u_arg[0] >= 0 && tcp->u_arg[0] < subcalls_table[i].nsubcalls) {
607 tcp->scno = subcalls_table[i].subcalls[tcp->u_arg[0]];
608 for (i = 0; i < tcp->u_nargs; i++)
609 tcp->u_arg[i] = tcp->u_arg[i + 1];
610 }
611 break;
612#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000613 }
614}
615#endif
616
617struct tcb *tcp_last = NULL;
618
619static int
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000620internal_syscall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000621{
622 /*
623 * We must always trace a few critical system calls in order to
624 * correctly support following forks in the presence of tracing
625 * qualifiers.
626 */
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000627 int (*func)();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000628
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000629 if (tcp->scno < 0 || tcp->scno >= nsyscalls)
630 return 0;
631
632 func = sysent[tcp->scno].sys_func;
633
634 if (sys_exit == func)
635 return internal_exit(tcp);
636
637 if ( sys_fork == func
638#if defined(FREEBSD) || defined(LINUX) || defined(SUNOS4)
639 || sys_vfork == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000640#endif
Dmitry V. Levin257e1572009-12-26 17:55:24 +0000641#ifdef LINUX
642 || sys_clone == func
643#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000644#if UNIXWARE > 2
645 || sys_rfork == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000646#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000647 )
648 return internal_fork(tcp);
649
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000650 if ( sys_execve == func
651#if defined(SPARC) || defined(SPARC64) || defined(SUNOS4)
652 || sys_execv == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000653#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000654#if UNIXWARE > 2
655 || sys_rexecve == func
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000656#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000657 )
658 return internal_exec(tcp);
659
660 if ( sys_waitpid == func
661 || sys_wait4 == func
662#if defined(SVR4) || defined(FREEBSD) || defined(SUNOS4)
663 || sys_wait == func
Roland McGrath923f7502003-01-09 06:53:27 +0000664#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000665#ifdef ALPHA
666 || sys_osf_wait4 == func
Roland McGrath08267b82004-02-20 22:56:43 +0000667#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000668 )
669 return internal_wait(tcp, 2);
670
671#if defined(LINUX) || defined(SVR4)
672 if (sys_waitid == func)
673 return internal_wait(tcp, 3);
674#endif
675
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000676 return 0;
677}
678
Wichert Akkermanc7926982000-04-10 22:22:31 +0000679
680#ifdef LINUX
681#if defined (I386)
682 static long eax;
683#elif defined (IA64)
684 long r8, r10, psr;
685 long ia32 = 0;
686#elif defined (POWERPC)
687 static long result,flags;
688#elif defined (M68K)
Andreas Schwabffca9e32010-05-28 20:53:14 +0200689 static long d0;
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000690#elif defined(BFIN)
691 static long r0;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000692#elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +0000693 static struct pt_regs regs;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000694#elif defined (ALPHA)
695 static long r0;
696 static long a3;
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000697#elif defined(AVR32)
698 static struct pt_regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000699#elif defined (SPARC) || defined (SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -0400700 static struct pt_regs regs;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000701 static unsigned long trap;
Roland McGrath542c2c62008-05-20 01:11:56 +0000702#elif defined(LINUX_MIPSN32)
703 static long long a3;
704 static long long r2;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000705#elif defined(MIPS)
706 static long a3;
707 static long r2;
Michal Ludvig10a88d02002-10-07 14:31:00 +0000708#elif defined(S390) || defined(S390X)
Wichert Akkermanc7926982000-04-10 22:22:31 +0000709 static long gpr2;
710 static long pc;
Michal Ludvig882eda82002-11-11 12:50:47 +0000711 static long syscall_mode;
Wichert Akkermanc1652e22001-03-27 12:17:16 +0000712#elif defined(HPPA)
713 static long r28;
Wichert Akkermanccef6372002-05-01 16:39:22 +0000714#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000715 static long r0;
Roland McGrathf5a47772003-06-26 22:40:42 +0000716#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000717 static long r9;
Michal Ludvig0e035502002-09-23 15:41:01 +0000718#elif defined(X86_64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000719 static long rax;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000720#elif defined(CRISV10) || defined(CRISV32)
721 static long r10;
Edgar E. Iglesias939caba2010-07-06 14:21:07 +0200722#elif defined(MICROBLAZE)
723 static long r3;
Roland McGrath761b5d72002-12-15 23:58:31 +0000724#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000725#endif /* LINUX */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000726#ifdef FREEBSD
727 struct reg regs;
Roland McGrath761b5d72002-12-15 23:58:31 +0000728#endif /* FREEBSD */
Wichert Akkermanc7926982000-04-10 22:22:31 +0000729
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000730int
Denys Vlasenkofb036672009-01-23 16:30:26 +0000731get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000732{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000733 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000734
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000735#ifdef LINUX
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000736# if defined(S390) || defined(S390X)
Roland McGrath96dc5142003-01-20 10:23:04 +0000737 if (tcp->flags & TCB_WAITEXECVE) {
738 /*
739 * When the execve system call completes successfully, the
740 * new process still has -ENOSYS (old style) or __NR_execve
741 * (new style) in gpr2. We cannot recover the scno again
742 * by disassembly, because the image that executed the
743 * syscall is gone now. Fortunately, we don't want it. We
744 * leave the flag set so that syscall_fixup can fake the
745 * result.
746 */
747 if (tcp->flags & TCB_INSYSCALL)
748 return 1;
749 /*
750 * This is the SIGTRAP after execve. We cannot try to read
751 * the system call here either.
752 */
753 tcp->flags &= ~TCB_WAITEXECVE;
754 return 0;
755 }
Roland McGrath2f924ca2003-06-26 22:23:28 +0000756
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000757 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Roland McGrath2f924ca2003-06-26 22:23:28 +0000758 return -1;
759
760 if (syscall_mode != -ENOSYS) {
761 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000762 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000763 */
764 scno = syscall_mode;
765 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000766 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000767 * Old style of "passing" the scno via the SVC instruction.
768 */
769
770 long opcode, offset_reg, tmp;
771 void * svc_addr;
772 int gpr_offset[16] = {PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
773 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
774 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
775 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15};
Roland McGrath761b5d72002-12-15 23:58:31 +0000776
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000777 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000778 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000779 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000780 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000781 if (errno) {
782 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000783 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000784 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000785
786 /*
787 * We have to check if the SVC got executed directly or via an
788 * EXECUTE instruction. In case of EXECUTE it is necessary to do
789 * instruction decoding to derive the system call number.
790 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
791 * so that this doesn't work if a SVC opcode is part of an EXECUTE
792 * opcode. Since there is no way to find out the opcode size this
793 * is the best we can do...
794 */
795
796 if ((opcode & 0xff00) == 0x0a00) {
797 /* SVC opcode */
798 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000799 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000800 else {
801 /* SVC got executed by EXECUTE instruction */
802
803 /*
804 * Do instruction decoding of EXECUTE. If you really want to
805 * understand this, read the Principles of Operations.
806 */
807 svc_addr = (void *) (opcode & 0xfff);
808
809 tmp = 0;
810 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000811 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000812 return -1;
813 svc_addr += tmp;
814
815 tmp = 0;
816 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000817 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000818 return -1;
819 svc_addr += tmp;
820
Denys Vlasenkofb036672009-01-23 16:30:26 +0000821 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000822 if (errno)
823 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000824# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000825 scno >>= 48;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000826# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000827 scno >>= 16;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000828# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000829 tmp = 0;
830 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000831 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000832 return -1;
833
834 scno = (scno | tmp) & 0xff;
835 }
836 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000837# elif defined (POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000838 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000839 return -1;
840 if (!(tcp->flags & TCB_INSYSCALL)) {
841 /* Check if we return from execve. */
842 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
843 tcp->flags &= ~TCB_WAITEXECVE;
844 return 0;
845 }
846 }
Andreas Schwabd69fa492010-07-12 21:39:57 +0200847
848# ifdef POWERPC64
849 if (!(tcp->flags & TCB_INSYSCALL)) {
850 static int currpers = -1;
851 long val;
852 int pid = tcp->pid;
853
854 /* Check for 64/32 bit mode. */
855 if (upeek(tcp, sizeof (unsigned long)*PT_MSR, &val) < 0)
856 return -1;
857 /* SF is bit 0 of MSR */
858 if (val < 0)
859 currpers = 0;
860 else
861 currpers = 1;
862 if (currpers != current_personality) {
863 static const char *const names[] = {"64 bit", "32 bit"};
864 set_personality(currpers);
Dmitry V. Levinbdafa1a2010-12-02 23:38:13 +0000865 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
Andreas Schwabd69fa492010-07-12 21:39:57 +0200866 pid, names[current_personality]);
867 }
868 }
869# endif
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000870# elif defined(AVR32)
871 /*
872 * Read complete register set in one go.
873 */
874 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
875 return -1;
876
877 /*
878 * We only need to grab the syscall number on syscall entry.
879 */
880 if (!(tcp->flags & TCB_INSYSCALL)) {
881 scno = regs.r8;
882
883 /* Check if we return from execve. */
884 if (tcp->flags & TCB_WAITEXECVE) {
885 tcp->flags &= ~TCB_WAITEXECVE;
886 return 0;
887 }
888 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000889# elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000890 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000891 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000892# elif defined (I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000893 if (upeek(tcp, 4*ORIG_EAX, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000894 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000895# elif defined (X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000896 if (upeek(tcp, 8*ORIG_RAX, &scno) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +0000897 return -1;
898
Roland McGrath761b5d72002-12-15 23:58:31 +0000899 if (!(tcp->flags & TCB_INSYSCALL)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000900 static int currpers = -1;
Michal Ludvig0e035502002-09-23 15:41:01 +0000901 long val;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000902 int pid = tcp->pid;
Michal Ludvig0e035502002-09-23 15:41:01 +0000903
904 /* Check CS register value. On x86-64 linux it is:
905 * 0x33 for long mode (64 bit)
906 * 0x23 for compatibility mode (32 bit)
Roland McGrath761b5d72002-12-15 23:58:31 +0000907 * It takes only one ptrace and thus doesn't need
Michal Ludvig0e035502002-09-23 15:41:01 +0000908 * to be cached.
909 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000910 if (upeek(tcp, 8*CS, &val) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +0000911 return -1;
Denys Vlasenko8236f252009-01-02 18:10:08 +0000912 switch (val) {
Michal Ludvig0e035502002-09-23 15:41:01 +0000913 case 0x23: currpers = 1; break;
914 case 0x33: currpers = 0; break;
915 default:
916 fprintf(stderr, "Unknown value CS=0x%02X while "
917 "detecting personality of process "
918 "PID=%d\n", (int)val, pid);
919 currpers = current_personality;
920 break;
921 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000922# if 0
Michal Ludvig0e035502002-09-23 15:41:01 +0000923 /* This version analyzes the opcode of a syscall instruction.
924 * (int 0x80 on i386 vs. syscall on x86-64)
925 * It works, but is too complicated.
926 */
927 unsigned long val, rip, i;
928
Denys Vlasenko8236f252009-01-02 18:10:08 +0000929 if (upeek(tcp, 8*RIP, &rip) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +0000930 perror("upeek(RIP)");
Roland McGrath761b5d72002-12-15 23:58:31 +0000931
Michal Ludvig0e035502002-09-23 15:41:01 +0000932 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
Denys Vlasenko8236f252009-01-02 18:10:08 +0000933 rip -= 2;
Michal Ludvig0e035502002-09-23 15:41:01 +0000934 errno = 0;
935
Denys Vlasenko8236f252009-01-02 18:10:08 +0000936 call = ptrace(PTRACE_PEEKTEXT, pid, (char *)rip, (char *)0);
Roland McGrath761b5d72002-12-15 23:58:31 +0000937 if (errno)
Dmitry V. Levinbdafa1a2010-12-02 23:38:13 +0000938 fprintf(stderr, "ptrace_peektext failed: %s\n",
Michal Ludvig0e035502002-09-23 15:41:01 +0000939 strerror(errno));
Denys Vlasenko8236f252009-01-02 18:10:08 +0000940 switch (call & 0xffff) {
Michal Ludvig0e035502002-09-23 15:41:01 +0000941 /* x86-64: syscall = 0x0f 0x05 */
942 case 0x050f: currpers = 0; break;
943 /* i386: int 0x80 = 0xcd 0x80 */
944 case 0x80cd: currpers = 1; break;
945 default:
946 currpers = current_personality;
Roland McGrath761b5d72002-12-15 23:58:31 +0000947 fprintf(stderr,
Michal Ludvig0e035502002-09-23 15:41:01 +0000948 "Unknown syscall opcode (0x%04X) while "
949 "detecting personality of process "
950 "PID=%d\n", (int)call, pid);
951 break;
952 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000953# endif
Denys Vlasenko8236f252009-01-02 18:10:08 +0000954 if (currpers != current_personality) {
955 static const char *const names[] = {"64 bit", "32 bit"};
Michal Ludvig0e035502002-09-23 15:41:01 +0000956 set_personality(currpers);
Dmitry V. Levinbdafa1a2010-12-02 23:38:13 +0000957 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
Michal Ludvig0e035502002-09-23 15:41:01 +0000958 pid, names[current_personality]);
959 }
Roland McGrath761b5d72002-12-15 23:58:31 +0000960 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000961# elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000962# define IA64_PSR_IS ((long)1 << 34)
Roland McGratheb9e2e82009-06-02 16:49:22 -0700963 if (upeek (tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000964 ia32 = (psr & IA64_PSR_IS) != 0;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000965 if (!(tcp->flags & TCB_INSYSCALL)) {
966 if (ia32) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000967 if (upeek(tcp, PT_R1, &scno) < 0) /* orig eax */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000968 return -1;
969 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700970 if (upeek (tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000971 return -1;
972 }
Roland McGrathba954762003-03-05 06:29:06 +0000973 /* Check if we return from execve. */
974 if (tcp->flags & TCB_WAITEXECVE) {
975 tcp->flags &= ~TCB_WAITEXECVE;
976 return 0;
977 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000978 } else {
979 /* syscall in progress */
Roland McGratheb9e2e82009-06-02 16:49:22 -0700980 if (upeek (tcp, PT_R8, &r8) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000981 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -0700982 if (upeek (tcp, PT_R10, &r10) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000983 return -1;
984 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000985# elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +0000986 /*
987 * Read complete register set in one go.
988 */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000989 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +0000990 return -1;
991
992 /*
993 * We only need to grab the syscall number on syscall entry.
994 */
995 if (regs.ARM_ip == 0) {
Roland McGrath9bc63402007-11-01 21:42:18 +0000996 if (!(tcp->flags & TCB_INSYSCALL)) {
997 /* Check if we return from execve. */
998 if (tcp->flags & TCB_WAITEXECVE) {
999 tcp->flags &= ~TCB_WAITEXECVE;
1000 return 0;
1001 }
1002 }
1003
Roland McGrath0f87c492003-06-03 23:29:04 +00001004 /*
1005 * Note: we only deal with only 32-bit CPUs here.
1006 */
1007 if (regs.ARM_cpsr & 0x20) {
1008 /*
1009 * Get the Thumb-mode system call number
1010 */
1011 scno = regs.ARM_r7;
1012 } else {
1013 /*
1014 * Get the ARM-mode system call number
1015 */
1016 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +00001017 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +00001018 if (errno)
1019 return -1;
1020
1021 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
1022 tcp->flags &= ~TCB_WAITEXECVE;
1023 return 0;
1024 }
1025
Roland McGrathf691bd22006-04-25 07:34:41 +00001026 /* Handle the EABI syscall convention. We do not
1027 bother converting structures between the two
1028 ABIs, but basic functionality should work even
1029 if strace and the traced program have different
1030 ABIs. */
1031 if (scno == 0xef000000) {
1032 scno = regs.ARM_r7;
1033 } else {
1034 if ((scno & 0x0ff00000) != 0x0f900000) {
1035 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1036 scno);
1037 return -1;
1038 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001039
Roland McGrathf691bd22006-04-25 07:34:41 +00001040 /*
1041 * Fixup the syscall number
1042 */
1043 scno &= 0x000fffff;
1044 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001045 }
Roland McGrath56703312008-05-20 01:35:55 +00001046 if (scno & 0x0f0000) {
1047 /*
1048 * Handle ARM specific syscall
1049 */
1050 set_personality(1);
1051 scno &= 0x0000ffff;
1052 } else
1053 set_personality(0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001054
1055 if (tcp->flags & TCB_INSYSCALL) {
1056 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1057 tcp->flags &= ~TCB_INSYSCALL;
1058 }
1059 } else {
1060 if (!(tcp->flags & TCB_INSYSCALL)) {
1061 fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
1062 tcp->flags |= TCB_INSYSCALL;
1063 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001064 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001065# elif defined (M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001066 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001067 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001068# elif defined (LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001069 unsigned long long regs[38];
1070
Roland McGratheb9e2e82009-06-02 16:49:22 -07001071 if (ptrace (PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001072 return -1;
1073 a3 = regs[REG_A3];
1074 r2 = regs[REG_V0];
1075
1076 if(!(tcp->flags & TCB_INSYSCALL)) {
1077 scno = r2;
1078
1079 /* Check if we return from execve. */
1080 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1081 tcp->flags &= ~TCB_WAITEXECVE;
1082 return 0;
1083 }
1084
1085 if (scno < 0 || scno > nsyscalls) {
1086 if(a3 == 0 || a3 == -1) {
1087 if(debug)
1088 fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
1089 return 0;
1090 }
1091 }
1092 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001093# elif defined (MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001094 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001095 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001096 if(!(tcp->flags & TCB_INSYSCALL)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001097 if (upeek(tcp, REG_V0, &scno) < 0)
1098 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001099
Roland McGrath542c2c62008-05-20 01:11:56 +00001100 /* Check if we return from execve. */
1101 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1102 tcp->flags &= ~TCB_WAITEXECVE;
1103 return 0;
1104 }
1105
Wichert Akkermanf90da011999-10-31 21:15:38 +00001106 if (scno < 0 || scno > nsyscalls) {
1107 if(a3 == 0 || a3 == -1) {
1108 if(debug)
1109 fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
1110 return 0;
1111 }
1112 }
1113 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001114 if (upeek(tcp, REG_V0, &r2) < 0)
1115 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001116 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001117# elif defined (ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001118 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001119 return -1;
1120
1121 if (!(tcp->flags & TCB_INSYSCALL)) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001122 if (upeek(tcp, REG_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001123 return -1;
1124
1125 /* Check if we return from execve. */
1126 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1127 tcp->flags &= ~TCB_WAITEXECVE;
1128 return 0;
1129 }
1130
1131 /*
1132 * Do some sanity checks to figure out if it's
1133 * really a syscall entry
1134 */
1135 if (scno < 0 || scno > nsyscalls) {
1136 if (a3 == 0 || a3 == -1) {
1137 if (debug)
1138 fprintf (stderr, "stray syscall exit: r0 = %ld\n", scno);
1139 return 0;
1140 }
1141 }
1142 }
1143 else {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001144 if (upeek(tcp, REG_R0, &r0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001145 return -1;
1146 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001147# elif defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001148 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001149 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001150 return -1;
1151
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001152 /* If we are entering, then disassemble the syscall trap. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001153 if (!(tcp->flags & TCB_INSYSCALL)) {
1154 /* Retrieve the syscall trap instruction. */
1155 errno = 0;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001156# if defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001157 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001158 trap >>= 32;
Mike Frysinger8566c502009-10-12 11:05:14 -04001159# else
1160 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001161# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001162 if (errno)
1163 return -1;
1164
1165 /* Disassemble the trap to see what personality to use. */
1166 switch (trap) {
1167 case 0x91d02010:
1168 /* Linux/SPARC syscall trap. */
1169 set_personality(0);
1170 break;
Wichert Akkermandacfb6e1999-06-03 14:21:07 +00001171 case 0x91d0206d:
1172 /* Linux/SPARC64 syscall trap. */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001173 set_personality(2);
1174 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175 case 0x91d02000:
1176 /* SunOS syscall trap. (pers 1) */
1177 fprintf(stderr,"syscall: SunOS no support\n");
1178 return -1;
1179 case 0x91d02008:
1180 /* Solaris 2.x syscall trap. (per 2) */
1181 set_personality(1);
Roland McGrath761b5d72002-12-15 23:58:31 +00001182 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001183 case 0x91d02009:
1184 /* NetBSD/FreeBSD syscall trap. */
1185 fprintf(stderr,"syscall: NetBSD/FreeBSD not supported\n");
1186 return -1;
1187 case 0x91d02027:
1188 /* Solaris 2.x gettimeofday */
1189 set_personality(1);
1190 break;
1191 default:
1192 /* Unknown syscall trap. */
1193 if(tcp->flags & TCB_WAITEXECVE) {
1194 tcp->flags &= ~TCB_WAITEXECVE;
1195 return 0;
1196 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001197# if defined (SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001198 fprintf(stderr,"syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001199# else
Mike Frysinger8566c502009-10-12 11:05:14 -04001200 fprintf(stderr,"syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001201# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001202 return -1;
1203 }
1204
1205 /* Extract the system call number from the registers. */
1206 if (trap == 0x91d02027)
1207 scno = 156;
1208 else
Mike Frysinger8566c502009-10-12 11:05:14 -04001209 scno = regs.u_regs[U_REG_G1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001210 if (scno == 0) {
Mike Frysinger8566c502009-10-12 11:05:14 -04001211 scno = regs.u_regs[U_REG_O0];
1212 memmove (&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001213 }
1214 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001215# elif defined(HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001216 if (upeek(tcp, PT_GR20, &scno) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001217 return -1;
1218 if (!(tcp->flags & TCB_INSYSCALL)) {
1219 /* Check if we return from execve. */
1220 if ((tcp->flags & TCB_WAITEXECVE)) {
1221 tcp->flags &= ~TCB_WAITEXECVE;
1222 return 0;
1223 }
1224 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001225# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001226 /*
1227 * In the new syscall ABI, the system call number is in R3.
1228 */
1229 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1230 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001231
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001232 if (scno < 0) {
1233 /* Odd as it may seem, a glibc bug has been known to cause
1234 glibc to issue bogus negative syscall numbers. So for
1235 our purposes, make strace print what it *should* have been */
1236 long correct_scno = (scno & 0xff);
1237 if (debug)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001238 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001239 "Detected glibc bug: bogus system call"
1240 " number = %ld, correcting to %ld\n",
1241 scno,
1242 correct_scno);
1243 scno = correct_scno;
1244 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00001245
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001246 if (!(tcp->flags & TCB_INSYSCALL)) {
1247 /* Check if we return from execve. */
1248 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1249 tcp->flags &= ~TCB_WAITEXECVE;
1250 return 0;
1251 }
1252 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001253# elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001254 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001255 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001256 scno &= 0xFFFF;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001257
1258 if (!(tcp->flags & TCB_INSYSCALL)) {
1259 /* Check if we return from execve. */
1260 if (tcp->flags & TCB_WAITEXECVE) {
1261 tcp->flags &= ~TCB_WAITEXECVE;
1262 return 0;
1263 }
1264 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001265# elif defined(CRISV10) || defined(CRISV32)
1266 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1267 return -1;
Chris Metcalfc8c66982009-12-28 10:00:15 -05001268# elif defined(TILE)
1269 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1270 return -1;
1271
1272 if (!(tcp->flags & TCB_INSYSCALL)) {
1273 /* Check if we return from execve. */
1274 if (tcp->flags & TCB_WAITEXECVE) {
1275 tcp->flags &= ~TCB_WAITEXECVE;
1276 return 0;
1277 }
1278 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001279# elif defined(MICROBLAZE)
1280 if (upeek(tcp, 0, &scno) < 0)
1281 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001282# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001283#endif /* LINUX */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001284
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001285#ifdef SUNOS4
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001286 if (upeek(tcp, uoff(u_arg[7]), &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001287 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001288#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001289 /* new syscall ABI returns result in R0 */
1290 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1291 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001292#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001293 /* ABI defines result returned in r9 */
1294 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1295 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001296#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001297
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001298#ifdef USE_PROCFS
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001299# ifdef HAVE_PR_SYSCALL
John Hughes25299712001-03-06 10:10:06 +00001300 scno = tcp->status.PR_SYSCALL;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001301# else
1302# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001303 scno = tcp->status.PR_WHAT;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001304# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001305 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001306 perror("pread");
1307 return -1;
1308 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001309 switch (regs.r_eax) {
1310 case SYS_syscall:
1311 case SYS___syscall:
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001312 pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int));
1313 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001314 default:
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001315 scno = regs.r_eax;
1316 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001317 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001318# endif /* FREEBSD */
1319# endif /* !HAVE_PR_SYSCALL */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001320#endif /* USE_PROCFS */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001321
Wichert Akkerman5ae21ea2000-05-01 01:53:59 +00001322 if (!(tcp->flags & TCB_INSYSCALL))
1323 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001324 return 1;
1325}
1326
Pavel Machek4dc3b142000-02-01 17:58:41 +00001327
Roland McGrath17352792005-06-07 23:21:26 +00001328long
Dmitry V. Levinbd136452011-02-18 23:19:47 +00001329known_scno(struct tcb *tcp)
Roland McGrath17352792005-06-07 23:21:26 +00001330{
1331 long scno = tcp->scno;
Dmitry V. Levinbd136452011-02-18 23:19:47 +00001332#if SUPPORTED_PERSONALITIES > 1
Roland McGrath17352792005-06-07 23:21:26 +00001333 if (scno >= 0 && scno < nsyscalls && sysent[scno].native_scno != 0)
1334 scno = sysent[scno].native_scno;
1335 else
Dmitry V. Levinbd136452011-02-18 23:19:47 +00001336#endif
Roland McGrath17352792005-06-07 23:21:26 +00001337 scno += NR_SYSCALL_BASE;
1338 return scno;
1339}
1340
Roland McGratheb9e2e82009-06-02 16:49:22 -07001341/* Called in trace_syscall() at each syscall entry and exit.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001342 * Returns:
Roland McGratheb9e2e82009-06-02 16:49:22 -07001343 * 0: "ignore this syscall", bail out of trace_syscall() silently.
1344 * 1: ok, continue in trace_syscall().
1345 * other: error, trace_syscall() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001346 * ("????" etc) and bail out.
1347 */
Roland McGratha4d48532005-06-08 20:45:28 +00001348static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001349syscall_fixup(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001350{
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001351#ifdef USE_PROCFS
Roland McGrath17352792005-06-07 23:21:26 +00001352 int scno = known_scno(tcp);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001353
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001354 if (!(tcp->flags & TCB_INSYSCALL)) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001355 if (tcp->status.PR_WHY != PR_SYSENTRY) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001356 if (
1357 scno == SYS_fork
1358#ifdef SYS_vfork
1359 || scno == SYS_vfork
1360#endif /* SYS_vfork */
John Hughes4e36a812001-04-18 15:11:51 +00001361#ifdef SYS_fork1
1362 || scno == SYS_fork1
1363#endif /* SYS_fork1 */
1364#ifdef SYS_forkall
1365 || scno == SYS_forkall
1366#endif /* SYS_forkall */
1367#ifdef SYS_rfork1
1368 || scno == SYS_rfork1
1369#endif /* SYS_fork1 */
1370#ifdef SYS_rforkall
1371 || scno == SYS_rforkall
1372#endif /* SYS_rforkall */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001373 ) {
1374 /* We are returning in the child, fake it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001375 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001376 trace_syscall(tcp);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001377 tcp->status.PR_WHY = PR_SYSEXIT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001378 }
1379 else {
1380 fprintf(stderr, "syscall: missing entry\n");
1381 tcp->flags |= TCB_INSYSCALL;
1382 }
1383 }
1384 }
1385 else {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001386 if (tcp->status.PR_WHY != PR_SYSEXIT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001387 fprintf(stderr, "syscall: missing exit\n");
1388 tcp->flags &= ~TCB_INSYSCALL;
1389 }
1390 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001391#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001392#ifdef SUNOS4
1393 if (!(tcp->flags & TCB_INSYSCALL)) {
1394 if (scno == 0) {
1395 fprintf(stderr, "syscall: missing entry\n");
1396 tcp->flags |= TCB_INSYSCALL;
1397 }
1398 }
1399 else {
1400 if (scno != 0) {
1401 if (debug) {
1402 /*
1403 * This happens when a signal handler
1404 * for a signal which interrupted a
1405 * a system call makes another system call.
1406 */
1407 fprintf(stderr, "syscall: missing exit\n");
1408 }
1409 tcp->flags &= ~TCB_INSYSCALL;
1410 }
1411 }
1412#endif /* SUNOS4 */
1413#ifdef LINUX
1414#if defined (I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001415 if (upeek(tcp, 4*EAX, &eax) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001416 return -1;
1417 if (eax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1418 if (debug)
1419 fprintf(stderr, "stray syscall exit: eax = %ld\n", eax);
1420 return 0;
1421 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001422#elif defined (X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001423 if (upeek(tcp, 8*RAX, &rax) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00001424 return -1;
Roland McGrath998fac72004-06-23 01:40:45 +00001425 if (current_personality == 1)
1426 rax = (long int)(int)rax; /* sign extend from 32 bits */
Michal Ludvig0e035502002-09-23 15:41:01 +00001427 if (rax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1428 if (debug)
1429 fprintf(stderr, "stray syscall exit: rax = %ld\n", rax);
1430 return 0;
1431 }
Michal Ludvig10a88d02002-10-07 14:31:00 +00001432#elif defined (S390) || defined (S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001433 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001434 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001435 if (syscall_mode != -ENOSYS)
1436 syscall_mode = tcp->scno;
1437 if (gpr2 != syscall_mode && !(tcp->flags & TCB_INSYSCALL)) {
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001438 if (debug)
1439 fprintf(stderr, "stray syscall exit: gpr2 = %ld\n", gpr2);
1440 return 0;
1441 }
Roland McGrath96dc5142003-01-20 10:23:04 +00001442 else if (((tcp->flags & (TCB_INSYSCALL|TCB_WAITEXECVE))
1443 == (TCB_INSYSCALL|TCB_WAITEXECVE))
1444 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1445 /*
1446 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1447 * flag set for the post-execve SIGTRAP to see and reset.
1448 */
1449 gpr2 = 0;
1450 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001451#elif defined (POWERPC)
1452# define SO_MASK 0x10000000
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001453 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001454 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001455 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &result) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001456 return -1;
1457 if (flags & SO_MASK)
1458 result = -result;
1459#elif defined (M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001460 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001461 return -1;
1462 if (d0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1463 if (debug)
1464 fprintf(stderr, "stray syscall exit: d0 = %ld\n", d0);
1465 return 0;
1466 }
1467#elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001468 /*
1469 * Nothing required
1470 */
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001471#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001472 if (upeek(tcp, PT_R0, &r0) < 0)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001473 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001474#elif defined (HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001475 if (upeek(tcp, PT_GR28, &r28) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001476 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001477#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001478 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001479 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001480 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001481 return -1;
1482 if (ia32 && r8 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1483 if (debug)
1484 fprintf(stderr, "stray syscall exit: r8 = %ld\n", r8);
1485 return 0;
1486 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001487#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001488 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001489 return -1;
1490 if (r10 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1491 if (debug)
1492 fprintf(stderr, "stray syscall exit: r10 = %ld\n", r10);
1493 return 0;
1494 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001495#elif defined(MICROBLAZE)
1496 if (upeek(tcp, 3 * 4, &r3) < 0)
1497 return -1;
1498 if (r3 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1499 if (debug)
1500 fprintf(stderr, "stray syscall exit: r3 = %ld\n", r3);
1501 return 0;
1502 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001503#endif
1504#endif /* LINUX */
Pavel Machek4dc3b142000-02-01 17:58:41 +00001505 return 1;
1506}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001507
Roland McGrathc1e45922008-05-27 23:18:29 +00001508#ifdef LINUX
1509/*
1510 * Check the syscall return value register value for whether it is
1511 * a negated errno code indicating an error, or a success return value.
1512 */
1513static inline int
1514is_negated_errno(unsigned long int val)
1515{
1516 unsigned long int max = -(long int) nerrnos;
1517 if (personality_wordsize[current_personality] < sizeof(val)) {
1518 val = (unsigned int) val;
1519 max = (unsigned int) max;
1520 }
1521 return val > max;
1522}
1523#endif
1524
Roland McGratha4d48532005-06-08 20:45:28 +00001525static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001526get_error(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001527{
1528 int u_error = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001529#ifdef LINUX
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001530 int check_errno = 1;
1531 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
1532 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1533 check_errno = 0;
1534 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001535# if defined(S390) || defined(S390X)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001536 if (check_errno && is_negated_errno(gpr2)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001537 tcp->u_rval = -1;
1538 u_error = -gpr2;
1539 }
1540 else {
1541 tcp->u_rval = gpr2;
1542 u_error = 0;
1543 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001544# elif defined(I386)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001545 if (check_errno && is_negated_errno(eax)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001546 tcp->u_rval = -1;
1547 u_error = -eax;
1548 }
1549 else {
1550 tcp->u_rval = eax;
1551 u_error = 0;
1552 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001553# elif defined(X86_64)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001554 if (check_errno && is_negated_errno(rax)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001555 tcp->u_rval = -1;
1556 u_error = -rax;
1557 }
1558 else {
1559 tcp->u_rval = rax;
1560 u_error = 0;
1561 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001562# elif defined(IA64)
Roland McGrathc1e45922008-05-27 23:18:29 +00001563 if (ia32) {
1564 int err;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001565
Roland McGrathc1e45922008-05-27 23:18:29 +00001566 err = (int)r8;
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001567 if (check_errno && is_negated_errno(err)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001568 tcp->u_rval = -1;
1569 u_error = -err;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001570 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001571 else {
1572 tcp->u_rval = err;
1573 u_error = 0;
1574 }
1575 } else {
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001576 if (check_errno && r10) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001577 tcp->u_rval = -1;
1578 u_error = r8;
1579 } else {
1580 tcp->u_rval = r8;
1581 u_error = 0;
1582 }
1583 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001584# elif defined(MIPS)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001585 if (check_errno && a3) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001586 tcp->u_rval = -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001587 u_error = r2;
1588 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001589 tcp->u_rval = r2;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001590 u_error = 0;
1591 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001592# elif defined(POWERPC)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001593 if (check_errno && is_negated_errno(result)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001594 tcp->u_rval = -1;
1595 u_error = -result;
1596 }
1597 else {
1598 tcp->u_rval = result;
1599 u_error = 0;
1600 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001601# elif defined(M68K)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001602 if (check_errno && is_negated_errno(d0)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001603 tcp->u_rval = -1;
1604 u_error = -d0;
1605 }
1606 else {
1607 tcp->u_rval = d0;
1608 u_error = 0;
1609 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001610# elif defined(ARM)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001611 if (check_errno && is_negated_errno(regs.ARM_r0)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001612 tcp->u_rval = -1;
Roland McGrath0f87c492003-06-03 23:29:04 +00001613 u_error = -regs.ARM_r0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001614 }
1615 else {
Roland McGrath0f87c492003-06-03 23:29:04 +00001616 tcp->u_rval = regs.ARM_r0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001617 u_error = 0;
1618 }
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001619# elif defined(AVR32)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001620 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001621 tcp->u_rval = -1;
1622 u_error = -regs.r12;
1623 }
1624 else {
1625 tcp->u_rval = regs.r12;
1626 u_error = 0;
1627 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001628# elif defined(BFIN)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001629 if (check_errno && is_negated_errno(r0)) {
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001630 tcp->u_rval = -1;
1631 u_error = -r0;
1632 } else {
1633 tcp->u_rval = r0;
1634 u_error = 0;
1635 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001636# elif defined(ALPHA)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001637 if (check_errno && a3) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001638 tcp->u_rval = -1;
1639 u_error = r0;
1640 }
1641 else {
1642 tcp->u_rval = r0;
1643 u_error = 0;
1644 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001645# elif defined(SPARC)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001646 if (check_errno && regs.psr & PSR_C) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001647 tcp->u_rval = -1;
Mike Frysinger8566c502009-10-12 11:05:14 -04001648 u_error = regs.u_regs[U_REG_O0];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001649 }
1650 else {
Mike Frysinger8566c502009-10-12 11:05:14 -04001651 tcp->u_rval = regs.u_regs[U_REG_O0];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001652 u_error = 0;
1653 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001654# elif defined(SPARC64)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001655 if (check_errno && regs.tstate & 0x1100000000UL) {
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001656 tcp->u_rval = -1;
Mike Frysinger8566c502009-10-12 11:05:14 -04001657 u_error = regs.u_regs[U_REG_O0];
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001658 }
1659 else {
Mike Frysinger8566c502009-10-12 11:05:14 -04001660 tcp->u_rval = regs.u_regs[U_REG_O0];
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001661 u_error = 0;
1662 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001663# elif defined(HPPA)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001664 if (check_errno && is_negated_errno(r28)) {
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001665 tcp->u_rval = -1;
1666 u_error = -r28;
1667 }
1668 else {
1669 tcp->u_rval = r28;
1670 u_error = 0;
1671 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001672# elif defined(SH)
Roland McGrathc1e45922008-05-27 23:18:29 +00001673 /* interpret R0 as return value or error number */
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001674 if (check_errno && is_negated_errno(r0)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001675 tcp->u_rval = -1;
1676 u_error = -r0;
1677 }
1678 else {
1679 tcp->u_rval = r0;
1680 u_error = 0;
1681 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001682# elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001683 /* interpret result as return value or error number */
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001684 if (check_errno && is_negated_errno(r9)) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001685 tcp->u_rval = -1;
1686 u_error = -r9;
1687 }
1688 else {
1689 tcp->u_rval = r9;
1690 u_error = 0;
1691 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001692# elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001693 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001694 tcp->u_rval = -1;
1695 u_error = -r10;
1696 }
1697 else {
1698 tcp->u_rval = r10;
1699 u_error = 0;
1700 }
Chris Metcalfc8c66982009-12-28 10:00:15 -05001701# elif defined(TILE)
1702 long rval;
1703 /* interpret result as return value or error number */
1704 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1705 return -1;
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001706 if (check_errno && rval < 0 && rval > -nerrnos) {
Chris Metcalfc8c66982009-12-28 10:00:15 -05001707 tcp->u_rval = -1;
1708 u_error = -rval;
1709 }
1710 else {
1711 tcp->u_rval = rval;
1712 u_error = 0;
1713 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001714# elif defined(MICROBLAZE)
1715 /* interpret result as return value or error number */
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001716 if (check_errno && is_negated_errno(r3)) {
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001717 tcp->u_rval = -1;
1718 u_error = -r3;
1719 }
1720 else {
1721 tcp->u_rval = r3;
1722 u_error = 0;
1723 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001724# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001725#endif /* LINUX */
1726#ifdef SUNOS4
1727 /* get error code from user struct */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001728 if (upeek(tcp, uoff(u_error), &u_error) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001729 return -1;
1730 u_error >>= 24; /* u_error is a char */
1731
1732 /* get system call return value */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001733 if (upeek(tcp, uoff(u_rval1), &tcp->u_rval) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001734 return -1;
1735#endif /* SUNOS4 */
1736#ifdef SVR4
1737#ifdef SPARC
1738 /* Judicious guessing goes a long way. */
1739 if (tcp->status.pr_reg[R_PSR] & 0x100000) {
1740 tcp->u_rval = -1;
1741 u_error = tcp->status.pr_reg[R_O0];
1742 }
1743 else {
1744 tcp->u_rval = tcp->status.pr_reg[R_O0];
1745 u_error = 0;
1746 }
1747#endif /* SPARC */
1748#ifdef I386
1749 /* Wanna know how to kill an hour single-stepping? */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001750 if (tcp->status.PR_REG[EFL] & 0x1) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001751 tcp->u_rval = -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001752 u_error = tcp->status.PR_REG[EAX];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001753 }
1754 else {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001755 tcp->u_rval = tcp->status.PR_REG[EAX];
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001756#ifdef HAVE_LONG_LONG
1757 tcp->u_lrval =
1758 ((unsigned long long) tcp->status.PR_REG[EDX] << 32) +
1759 tcp->status.PR_REG[EAX];
1760#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001761 u_error = 0;
1762 }
1763#endif /* I386 */
Michal Ludvig0e035502002-09-23 15:41:01 +00001764#ifdef X86_64
1765 /* Wanna know how to kill an hour single-stepping? */
1766 if (tcp->status.PR_REG[EFLAGS] & 0x1) {
1767 tcp->u_rval = -1;
1768 u_error = tcp->status.PR_REG[RAX];
1769 }
1770 else {
1771 tcp->u_rval = tcp->status.PR_REG[RAX];
1772 u_error = 0;
1773 }
1774#endif /* X86_64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001775#ifdef MIPS
1776 if (tcp->status.pr_reg[CTX_A3]) {
1777 tcp->u_rval = -1;
1778 u_error = tcp->status.pr_reg[CTX_V0];
1779 }
1780 else {
1781 tcp->u_rval = tcp->status.pr_reg[CTX_V0];
1782 u_error = 0;
1783 }
1784#endif /* MIPS */
1785#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001786#ifdef FREEBSD
1787 if (regs.r_eflags & PSL_C) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001788 tcp->u_rval = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001789 u_error = regs.r_eax;
1790 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001791 tcp->u_rval = regs.r_eax;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001792 tcp->u_lrval =
1793 ((unsigned long long) regs.r_edx << 32) + regs.r_eax;
1794 u_error = 0;
1795 }
Roland McGrath761b5d72002-12-15 23:58:31 +00001796#endif /* FREEBSD */
Pavel Machek4dc3b142000-02-01 17:58:41 +00001797 tcp->u_error = u_error;
1798 return 1;
1799}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001800
Roland McGrathb69f81b2002-12-21 23:25:18 +00001801int
1802force_result(tcp, error, rval)
1803 struct tcb *tcp;
1804 int error;
1805 long rval;
1806{
1807#ifdef LINUX
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001808# if defined(S390) || defined(S390X)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001809 gpr2 = error ? -error : rval;
Roland McGrathb69f81b2002-12-21 23:25:18 +00001810 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_GPR2, gpr2) < 0)
1811 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001812# elif defined(I386)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001813 eax = error ? -error : rval;
1814 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(EAX * 4), eax) < 0)
1815 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001816# elif defined(X86_64)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001817 rax = error ? -error : rval;
Roland McGrath998fac72004-06-23 01:40:45 +00001818 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(RAX * 8), rax) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001819 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001820# elif defined(IA64)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001821 if (ia32) {
1822 r8 = error ? -error : rval;
1823 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0)
1824 return -1;
1825 }
1826 else {
1827 if (error) {
1828 r8 = error;
1829 r10 = -1;
1830 }
1831 else {
1832 r8 = rval;
1833 r10 = 0;
1834 }
1835 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0 ||
1836 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R10), r10) < 0)
1837 return -1;
1838 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001839# elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001840 r0 = error ? -error : rval;
1841 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_R0, r0) < 0)
1842 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001843# elif defined(MIPS)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001844 if (error) {
1845 r2 = error;
1846 a3 = -1;
1847 }
1848 else {
1849 r2 = rval;
1850 a3 = 0;
1851 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001852 /* PTRACE_POKEUSER is OK even for n32 since rval is only a long. */
Roland McGrathb69f81b2002-12-21 23:25:18 +00001853 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1854 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), r2) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001855 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001856# elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001857 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001858 return -1;
1859 if (error) {
1860 flags |= SO_MASK;
1861 result = error;
1862 }
1863 else {
1864 flags &= ~SO_MASK;
1865 result = rval;
1866 }
Roland McGratheb285352003-01-14 09:59:00 +00001867 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_CCR), flags) < 0 ||
1868 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_R3), result) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001869 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001870# elif defined(M68K)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001871 d0 = error ? -error : rval;
1872 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_D0), d0) < 0)
1873 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001874# elif defined(ARM)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001875 regs.ARM_r0 = error ? -error : rval;
1876 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*0), regs.ARM_r0) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001877 return -1;
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001878# elif defined(AVR32)
1879 regs.r12 = error ? -error : rval;
1880 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_R12, regs.r12) < 0)
1881 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001882# elif defined(ALPHA)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001883 if (error) {
1884 a3 = -1;
1885 r0 = error;
1886 }
1887 else {
1888 a3 = 0;
1889 r0 = rval;
1890 }
1891 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1892 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R0), r0) < 0)
1893 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001894# elif defined(SPARC)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001895 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1896 return -1;
1897 if (error) {
Mike Frysinger8566c502009-10-12 11:05:14 -04001898 regs.psr |= PSR_C;
1899 regs.u_regs[U_REG_O0] = error;
Roland McGrathb69f81b2002-12-21 23:25:18 +00001900 }
1901 else {
Mike Frysinger8566c502009-10-12 11:05:14 -04001902 regs.psr &= ~PSR_C;
1903 regs.u_regs[U_REG_O0] = rval;
Roland McGrathb69f81b2002-12-21 23:25:18 +00001904 }
1905 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1906 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001907# elif defined(SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001908 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1909 return -1;
1910 if (error) {
Mike Frysinger8566c502009-10-12 11:05:14 -04001911 regs.tstate |= 0x1100000000UL;
1912 regs.u_regs[U_REG_O0] = error;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001913 }
1914 else {
Mike Frysinger8566c502009-10-12 11:05:14 -04001915 regs.tstate &= ~0x1100000000UL;
1916 regs.u_regs[U_REG_O0] = rval;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001917 }
1918 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1919 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001920# elif defined(HPPA)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001921 r28 = error ? -error : rval;
1922 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR28), r28) < 0)
1923 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001924# elif defined(SH)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001925 r0 = error ? -error : rval;
1926 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*REG_REG0), r0) < 0)
1927 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001928# elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001929 r9 = error ? -error : rval;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001930 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_GENERAL(9), r9) < 0)
1931 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001932# endif
Roland McGrathb69f81b2002-12-21 23:25:18 +00001933#endif /* LINUX */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001934
Roland McGrathb69f81b2002-12-21 23:25:18 +00001935#ifdef SUNOS4
Roland McGratheb9e2e82009-06-02 16:49:22 -07001936 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_error),
1937 error << 24) < 0 ||
1938 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_rval1), rval) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001939 return -1;
1940#endif /* SUNOS4 */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001941
Roland McGrathb69f81b2002-12-21 23:25:18 +00001942#ifdef SVR4
1943 /* XXX no clue */
1944 return -1;
1945#endif /* SVR4 */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001946
Roland McGrathb69f81b2002-12-21 23:25:18 +00001947#ifdef FREEBSD
1948 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001949 perror("pread");
1950 return -1;
1951 }
Roland McGrathb69f81b2002-12-21 23:25:18 +00001952 if (error) {
1953 regs.r_eflags |= PSL_C;
1954 regs.r_eax = error;
1955 }
1956 else {
1957 regs.r_eflags &= ~PSL_C;
1958 regs.r_eax = rval;
1959 }
1960 if (pwrite(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001961 perror("pwrite");
1962 return -1;
1963 }
Roland McGrathb69f81b2002-12-21 23:25:18 +00001964#endif /* FREEBSD */
1965
1966 /* All branches reach here on success (only). */
1967 tcp->u_error = error;
1968 tcp->u_rval = rval;
1969 return 0;
1970}
1971
Roland McGratha4d48532005-06-08 20:45:28 +00001972static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001973syscall_enter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001974{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001975#ifdef LINUX
Michal Ludvig10a88d02002-10-07 14:31:00 +00001976#if defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001977 {
1978 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001979 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1980 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00001981 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001982 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001983 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001984 if (upeek(tcp,i==0 ? PT_ORIGGPR2:PT_GPR2+i*sizeof(long), &tcp->u_arg[i]) < 0)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001985 return -1;
1986 }
1987 }
1988#elif defined (ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001989 {
1990 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001991 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1992 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00001993 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001994 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001995 for (i = 0; i < tcp->u_nargs; i++) {
Wichert Akkermanb859bea1999-04-18 22:50:50 +00001996 /* WTA: if scno is out-of-bounds this will bomb. Add range-check
1997 * for scno somewhere above here!
1998 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001999 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002000 return -1;
2001 }
2002 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002003#elif defined (IA64)
2004 {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002005 if (!ia32) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00002006 unsigned long *out0, cfm, sof, sol, i;
2007 long rbs_end;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002008 /* be backwards compatible with kernel < 2.4.4... */
2009# ifndef PT_RBS_END
2010# define PT_RBS_END PT_AR_BSP
2011# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002012
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002013 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002014 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002015 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002016 return -1;
2017
2018 sof = (cfm >> 0) & 0x7f;
2019 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002020 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002021
2022 if (tcp->scno >= 0 && tcp->scno < nsyscalls
2023 && sysent[tcp->scno].nargs != -1)
2024 tcp->u_nargs = sysent[tcp->scno].nargs;
2025 else
2026 tcp->u_nargs = MAX_ARGS;
2027 for (i = 0; i < tcp->u_nargs; ++i) {
2028 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
2029 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
2030 return -1;
2031 }
2032 } else {
2033 int i;
2034
2035 if (/* EBX = out0 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002036 upeek(tcp, PT_R11, (long *) &tcp->u_arg[0]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002037 /* ECX = out1 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002038 || upeek(tcp, PT_R9, (long *) &tcp->u_arg[1]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002039 /* EDX = out2 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002040 || upeek(tcp, PT_R10, (long *) &tcp->u_arg[2]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002041 /* ESI = out3 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002042 || upeek(tcp, PT_R14, (long *) &tcp->u_arg[3]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002043 /* EDI = out4 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002044 || upeek(tcp, PT_R15, (long *) &tcp->u_arg[4]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002045 /* EBP = out5 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002046 || upeek(tcp, PT_R13, (long *) &tcp->u_arg[5]) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002047 return -1;
2048
2049 for (i = 0; i < 6; ++i)
2050 /* truncate away IVE sign-extension */
2051 tcp->u_arg[i] &= 0xffffffff;
2052
2053 if (tcp->scno >= 0 && tcp->scno < nsyscalls
2054 && sysent[tcp->scno].nargs != -1)
2055 tcp->u_nargs = sysent[tcp->scno].nargs;
2056 else
2057 tcp->u_nargs = 5;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002058 }
2059 }
Roland McGrath542c2c62008-05-20 01:11:56 +00002060#elif defined (LINUX_MIPSN32) || defined (LINUX_MIPSN64)
2061 /* N32 and N64 both use up to six registers. */
2062 {
2063 unsigned long long regs[38];
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002064 int i, nargs;
Roland McGrath542c2c62008-05-20 01:11:56 +00002065
2066 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2067 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrathc1e45922008-05-27 23:18:29 +00002068 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002069 nargs = tcp->u_nargs = MAX_ARGS;
Roland McGrath542c2c62008-05-20 01:11:56 +00002070
David Daney20037042010-02-09 21:22:30 +00002071 if (ptrace (PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00002072 return -1;
2073
Roland McGratheb9e2e82009-06-02 16:49:22 -07002074 for(i = 0; i < nargs; i++) {
Roland McGrath542c2c62008-05-20 01:11:56 +00002075 tcp->u_arg[i] = regs[REG_A0 + i];
2076# if defined (LINUX_MIPSN32)
2077 tcp->ext_arg[i] = regs[REG_A0 + i];
2078# endif
2079 }
2080 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00002081#elif defined (MIPS)
2082 {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002083 long sp;
2084 int i, nargs;
Wichert Akkermanf90da011999-10-31 21:15:38 +00002085
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002086 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2087 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002088 else
Dmitry V. Levin414fe7d2009-07-08 11:21:17 +00002089 nargs = tcp->u_nargs = MAX_ARGS;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002090 if(nargs > 4) {
Dmitry V. Levin414fe7d2009-07-08 11:21:17 +00002091 if(upeek(tcp, REG_SP, &sp) < 0)
2092 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002093 for(i = 0; i < 4; i++) {
Dmitry V. Levin414fe7d2009-07-08 11:21:17 +00002094 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i])<0)
2095 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00002096 }
2097 umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]),
2098 (char *)(tcp->u_arg + 4));
2099 } else {
Dmitry V. Levin414fe7d2009-07-08 11:21:17 +00002100 for(i = 0; i < nargs; i++) {
2101 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
2102 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00002103 }
2104 }
2105 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002106#elif defined (POWERPC)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002107# ifndef PT_ORIG_R3
2108# define PT_ORIG_R3 34
2109# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002110 {
2111 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002112 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2113 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002114 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002115 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002116 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002117 if (upeek(tcp, (i==0) ?
Roland McGratheb285352003-01-14 09:59:00 +00002118 (sizeof(unsigned long)*PT_ORIG_R3) :
2119 ((i+PT_R3)*sizeof(unsigned long)),
2120 &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002121 return -1;
2122 }
2123 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002124#elif defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002125 {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002126 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002127
2128 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2129 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002130 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002131 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002132 for (i = 0; i < tcp->u_nargs; i++)
Mike Frysinger8566c502009-10-12 11:05:14 -04002133 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002134 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002135#elif defined (HPPA)
2136 {
2137 int i;
2138
2139 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2140 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002141 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002142 tcp->u_nargs = MAX_ARGS;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002143 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002144 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002145 return -1;
2146 }
2147 }
Roland McGrath0f87c492003-06-03 23:29:04 +00002148#elif defined(ARM)
2149 {
2150 int i;
2151
2152 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2153 tcp->u_nargs = sysent[tcp->scno].nargs;
2154 else
2155 tcp->u_nargs = MAX_ARGS;
2156 for (i = 0; i < tcp->u_nargs; i++)
2157 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002158 }
2159#elif defined(AVR32)
2160 tcp->u_nargs = sysent[tcp->scno].nargs;
2161 tcp->u_arg[0] = regs.r12;
2162 tcp->u_arg[1] = regs.r11;
2163 tcp->u_arg[2] = regs.r10;
2164 tcp->u_arg[3] = regs.r9;
2165 tcp->u_arg[4] = regs.r5;
2166 tcp->u_arg[5] = regs.r3;
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00002167#elif defined(BFIN)
2168 {
2169 int i;
2170 int argreg[] = {PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5};
2171
2172 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2173 tcp->u_nargs = sysent[tcp->scno].nargs;
2174 else
2175 tcp->u_nargs = sizeof(argreg) / sizeof(argreg[0]);
2176
2177 for (i = 0; i < tcp->u_nargs; ++i)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002178 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00002179 return -1;
2180 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00002181#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002182 {
2183 int i;
2184 static int syscall_regs[] = {
2185 REG_REG0+4, REG_REG0+5, REG_REG0+6, REG_REG0+7,
2186 REG_REG0, REG_REG0+1, REG_REG0+2
2187 };
Wichert Akkermanccef6372002-05-01 16:39:22 +00002188
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002189 tcp->u_nargs = sysent[tcp->scno].nargs;
2190 for (i = 0; i < tcp->u_nargs; i++) {
2191 if (upeek(tcp, 4*syscall_regs[i], &tcp->u_arg[i]) < 0)
2192 return -1;
2193 }
2194 }
Roland McGrathf5a47772003-06-26 22:40:42 +00002195#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00002196 {
2197 int i;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002198 /* Registers used by SH5 Linux system calls for parameters */
Roland McGrathe1e584b2003-06-02 19:18:58 +00002199 static int syscall_regs[] = { 2, 3, 4, 5, 6, 7 };
2200
2201 /*
2202 * TODO: should also check that the number of arguments encoded
2203 * in the trap number matches the number strace expects.
2204 */
2205 /*
Dmitry V. Levin414fe7d2009-07-08 11:21:17 +00002206 assert(sysent[tcp->scno].nargs <
2207 sizeof(syscall_regs)/sizeof(syscall_regs[0]));
Roland McGrathe1e584b2003-06-02 19:18:58 +00002208 */
2209
2210 tcp->u_nargs = sysent[tcp->scno].nargs;
2211 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002212 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00002213 return -1;
2214 }
2215 }
2216
Michal Ludvig0e035502002-09-23 15:41:01 +00002217#elif defined(X86_64)
2218 {
2219 int i;
2220 static int argreg[SUPPORTED_PERSONALITIES][MAX_ARGS] = {
2221 {RDI,RSI,RDX,R10,R8,R9}, /* x86-64 ABI */
Roland McGrath5a9c6ad2005-02-02 03:06:52 +00002222 {RBX,RCX,RDX,RSI,RDI,RBP} /* i386 ABI */
Michal Ludvig0e035502002-09-23 15:41:01 +00002223 };
Roland McGrath761b5d72002-12-15 23:58:31 +00002224
Michal Ludvig0e035502002-09-23 15:41:01 +00002225 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2226 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002227 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002228 tcp->u_nargs = MAX_ARGS;
Michal Ludvig0e035502002-09-23 15:41:01 +00002229 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002230 if (upeek(tcp, argreg[current_personality][i]*8, &tcp->u_arg[i]) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00002231 return -1;
2232 }
2233 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02002234#elif defined(MICROBLAZE)
2235 {
2236 int i;
2237 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
2238 tcp->u_nargs = sysent[tcp->scno].nargs;
2239 else
2240 tcp->u_nargs = 0;
2241 for (i = 0; i < tcp->u_nargs; i++) {
2242 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
2243 return -1;
2244 }
2245 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002246#elif defined(CRISV10) || defined(CRISV32)
2247 {
2248 int i;
2249 static const int crisregs[] = {
2250 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
2251 4*PT_R13, 4*PT_MOF, 4*PT_SRP
2252 };
2253
2254 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
2255 tcp->u_nargs = sysent[tcp->scno].nargs;
2256 else
2257 tcp->u_nargs = 0;
2258 for (i = 0; i < tcp->u_nargs; i++) {
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00002259 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002260 return -1;
2261 }
2262 }
Chris Metcalfc8c66982009-12-28 10:00:15 -05002263#elif defined(TILE)
2264 {
2265 int i;
2266 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2267 tcp->u_nargs = sysent[tcp->scno].nargs;
2268 else
2269 tcp->u_nargs = MAX_ARGS;
2270 for (i = 0; i < tcp->u_nargs; ++i) {
2271 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
2272 return -1;
2273 }
2274 }
Andreas Schwab246888d2010-06-05 21:50:30 +02002275#elif defined (M68K)
2276 {
2277 int i;
2278 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2279 tcp->u_nargs = sysent[tcp->scno].nargs;
2280 else
2281 tcp->u_nargs = MAX_ARGS;
2282 for (i = 0; i < tcp->u_nargs; i++) {
2283 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
2284 return -1;
2285 }
2286 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00002287#else /* Other architecture (like i386) (32bits specific) */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002288 {
2289 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002290 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2291 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002292 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002293 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002294 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002295 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002296 return -1;
2297 }
2298 }
Roland McGrath761b5d72002-12-15 23:58:31 +00002299#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002300#endif /* LINUX */
2301#ifdef SUNOS4
2302 {
2303 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002304 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2305 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002306 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002307 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002308 for (i = 0; i < tcp->u_nargs; i++) {
2309 struct user *u;
2310
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002311 if (upeek(tcp, uoff(u_arg[0]) +
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002312 (i*sizeof(u->u_arg[0])), &tcp->u_arg[i]) < 0)
2313 return -1;
2314 }
2315 }
2316#endif /* SUNOS4 */
2317#ifdef SVR4
2318#ifdef MIPS
2319 /*
2320 * SGI is broken: even though it has pr_sysarg, it doesn't
2321 * set them on system call entry. Get a clue.
2322 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002323 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002324 tcp->u_nargs = sysent[tcp->scno].nargs;
2325 else
2326 tcp->u_nargs = tcp->status.pr_nsysarg;
2327 if (tcp->u_nargs > 4) {
2328 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2329 4*sizeof(tcp->u_arg[0]));
2330 umoven(tcp, tcp->status.pr_reg[CTX_SP] + 16,
2331 (tcp->u_nargs - 4)*sizeof(tcp->u_arg[0]), (char *) (tcp->u_arg + 4));
2332 }
2333 else {
2334 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2335 tcp->u_nargs*sizeof(tcp->u_arg[0]));
2336 }
John Hughes25299712001-03-06 10:10:06 +00002337#elif UNIXWARE >= 2
2338 /*
2339 * Like SGI, UnixWare doesn't set pr_sysarg until system call exit
2340 */
2341 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2342 tcp->u_nargs = sysent[tcp->scno].nargs;
2343 else
2344 tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;
2345 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
2346 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2347#elif defined (HAVE_PR_SYSCALL)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002348 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002349 tcp->u_nargs = sysent[tcp->scno].nargs;
2350 else
2351 tcp->u_nargs = tcp->status.pr_nsysarg;
2352 {
2353 int i;
2354 for (i = 0; i < tcp->u_nargs; i++)
2355 tcp->u_arg[i] = tcp->status.pr_sysarg[i];
2356 }
John Hughes25299712001-03-06 10:10:06 +00002357#elif defined (I386)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002358 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002359 tcp->u_nargs = sysent[tcp->scno].nargs;
2360 else
2361 tcp->u_nargs = 5;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002362 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002363 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
John Hughes25299712001-03-06 10:10:06 +00002364#else
2365 I DONT KNOW WHAT TO DO
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002366#endif /* !HAVE_PR_SYSCALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002367#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002368#ifdef FREEBSD
2369 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2370 sysent[tcp->scno].nargs > tcp->status.val)
2371 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002372 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002373 tcp->u_nargs = tcp->status.val;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002374 if (tcp->u_nargs < 0)
2375 tcp->u_nargs = 0;
2376 if (tcp->u_nargs > MAX_ARGS)
2377 tcp->u_nargs = MAX_ARGS;
2378 switch(regs.r_eax) {
2379 case SYS___syscall:
2380 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2381 regs.r_esp + sizeof(int) + sizeof(quad_t));
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002382 break;
2383 case SYS_syscall:
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002384 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2385 regs.r_esp + 2 * sizeof(int));
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002386 break;
2387 default:
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002388 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2389 regs.r_esp + sizeof(int));
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002390 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002391 }
2392#endif /* FREEBSD */
Pavel Machek4dc3b142000-02-01 17:58:41 +00002393 return 1;
2394}
2395
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002396static int
2397trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002398{
2399 int sys_res;
2400 struct timeval tv;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002401 int res, scno_good;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002402 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002403
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002404 /* Measure the exit time as early as possible to avoid errors. */
2405 if (dtime || cflag)
2406 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002407
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002408 /* BTW, why we don't just memorize syscall no. on entry
2409 * in tcp->something?
2410 */
2411 scno_good = res = get_scno(tcp);
2412 if (res == 0)
2413 return res;
2414 if (res == 1)
2415 res = syscall_fixup(tcp);
2416 if (res == 0)
2417 return res;
2418 if (res == 1)
2419 res = get_error(tcp);
2420 if (res == 0)
2421 return res;
2422 if (res == 1)
2423 internal_syscall(tcp);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002424
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002425 if (res == 1 && tcp->scno >= 0 && tcp->scno < nsyscalls &&
2426 !(qual_flags[tcp->scno] & QUAL_TRACE)) {
Pavel Machek4dc3b142000-02-01 17:58:41 +00002427 tcp->flags &= ~TCB_INSYSCALL;
2428 return 0;
2429 }
2430
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002431 if (tcp->flags & TCB_REPRINT) {
2432 printleader(tcp);
2433 tprintf("<... ");
2434 if (scno_good != 1)
2435 tprintf("????");
2436 else if (tcp->scno >= nsyscalls || tcp->scno < 0)
2437 tprintf("syscall_%lu", tcp->scno);
2438 else
2439 tprintf("%s", sysent[tcp->scno].sys_name);
2440 tprintf(" resumed> ");
2441 }
2442
2443 if (cflag) {
2444 struct timeval t = tv;
2445 int rc = count_syscall(tcp, &t);
2446 if (cflag == CFLAG_ONLY_STATS)
2447 {
2448 tcp->flags &= ~TCB_INSYSCALL;
2449 return rc;
2450 }
2451 }
2452
2453 if (res != 1) {
2454 tprintf(") ");
2455 tabto(acolumn);
2456 tprintf("= ? <unavailable>");
2457 printtrailer();
2458 tcp->flags &= ~TCB_INSYSCALL;
2459 return res;
2460 }
2461
2462 if (tcp->scno >= nsyscalls || tcp->scno < 0
2463 || (qual_flags[tcp->scno] & QUAL_RAW))
2464 sys_res = printargs(tcp);
2465 else {
2466 if (not_failing_only && tcp->u_error)
2467 return 0; /* ignore failed syscalls */
2468 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2469 }
2470
2471 u_error = tcp->u_error;
2472 tprintf(") ");
2473 tabto(acolumn);
2474 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2475 qual_flags[tcp->scno] & QUAL_RAW) {
2476 if (u_error)
2477 tprintf("= -1 (errno %ld)", u_error);
2478 else
2479 tprintf("= %#lx", tcp->u_rval);
2480 }
2481 else if (!(sys_res & RVAL_NONE) && u_error) {
2482 switch (u_error) {
2483#ifdef LINUX
2484 case ERESTARTSYS:
2485 tprintf("= ? ERESTARTSYS (To be restarted)");
2486 break;
2487 case ERESTARTNOINTR:
2488 tprintf("= ? ERESTARTNOINTR (To be restarted)");
2489 break;
2490 case ERESTARTNOHAND:
2491 tprintf("= ? ERESTARTNOHAND (To be restarted)");
2492 break;
2493 case ERESTART_RESTARTBLOCK:
2494 tprintf("= ? ERESTART_RESTARTBLOCK (To be restarted)");
2495 break;
2496#endif /* LINUX */
2497 default:
2498 tprintf("= -1 ");
2499 if (u_error < 0)
2500 tprintf("E??? (errno %ld)", u_error);
2501 else if (u_error < nerrnos)
2502 tprintf("%s (%s)", errnoent[u_error],
2503 strerror(u_error));
2504 else
2505 tprintf("ERRNO_%ld (%s)", u_error,
2506 strerror(u_error));
2507 break;
2508 }
2509 if ((sys_res & RVAL_STR) && tcp->auxstr)
2510 tprintf(" (%s)", tcp->auxstr);
2511 }
2512 else {
2513 if (sys_res & RVAL_NONE)
2514 tprintf("= ?");
2515 else {
2516 switch (sys_res & RVAL_MASK) {
2517 case RVAL_HEX:
2518 tprintf("= %#lx", tcp->u_rval);
2519 break;
2520 case RVAL_OCTAL:
2521 tprintf("= %#lo", tcp->u_rval);
2522 break;
2523 case RVAL_UDECIMAL:
2524 tprintf("= %lu", tcp->u_rval);
2525 break;
2526 case RVAL_DECIMAL:
2527 tprintf("= %ld", tcp->u_rval);
2528 break;
2529#ifdef HAVE_LONG_LONG
2530 case RVAL_LHEX:
2531 tprintf("= %#llx", tcp->u_lrval);
2532 break;
2533 case RVAL_LOCTAL:
2534 tprintf("= %#llo", tcp->u_lrval);
2535 break;
2536 case RVAL_LUDECIMAL:
2537 tprintf("= %llu", tcp->u_lrval);
2538 break;
2539 case RVAL_LDECIMAL:
2540 tprintf("= %lld", tcp->u_lrval);
2541 break;
2542#endif
2543 default:
2544 fprintf(stderr,
2545 "invalid rval format\n");
2546 break;
2547 }
2548 }
2549 if ((sys_res & RVAL_STR) && tcp->auxstr)
2550 tprintf(" (%s)", tcp->auxstr);
2551 }
2552 if (dtime) {
2553 tv_sub(&tv, &tv, &tcp->etime);
2554 tprintf(" <%ld.%06ld>",
2555 (long) tv.tv_sec, (long) tv.tv_usec);
2556 }
2557 printtrailer();
2558
2559 dumpio(tcp);
2560 if (fflush(tcp->outf) == EOF)
2561 return -1;
2562 tcp->flags &= ~TCB_INSYSCALL;
2563 return 0;
2564}
2565
2566static int
2567trace_syscall_entering(struct tcb *tcp)
2568{
2569 int sys_res;
2570 int res, scno_good;
2571
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002572 scno_good = res = get_scno(tcp);
2573 if (res == 0)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002574 return res;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002575 if (res == 1)
2576 res = syscall_fixup(tcp);
2577 if (res == 0)
2578 return res;
2579 if (res == 1)
2580 res = syscall_enter(tcp);
2581 if (res == 0)
2582 return res;
2583
2584 if (res != 1) {
2585 printleader(tcp);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002586 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002587 tcp_last = tcp;
2588 if (scno_good != 1)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002589 tprintf("????" /* anti-trigraph gap */ "(");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002590 else if (tcp->scno >= nsyscalls || tcp->scno < 0)
2591 tprintf("syscall_%lu(", tcp->scno);
2592 else
2593 tprintf("%s(", sysent[tcp->scno].sys_name);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002594 /*
2595 * " <unavailable>" will be added later by the code which
2596 * detects ptrace errors.
2597 */
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002598 tcp->flags |= TCB_INSYSCALL;
2599 return res;
2600 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002601
Roland McGrath17352792005-06-07 23:21:26 +00002602 switch (known_scno(tcp)) {
Roland McGrathd5bd7e62008-08-25 03:16:26 +00002603#ifdef SYS_socket_subcall
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002604 case SYS_socketcall:
2605 decode_subcall(tcp, SYS_socket_subcall,
2606 SYS_socket_nsubcalls, deref_style);
2607 break;
Roland McGrathd5bd7e62008-08-25 03:16:26 +00002608#endif
2609#ifdef SYS_ipc_subcall
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002610 case SYS_ipc:
2611 decode_subcall(tcp, SYS_ipc_subcall,
2612 SYS_ipc_nsubcalls, shift_style);
2613 break;
Roland McGrathd5bd7e62008-08-25 03:16:26 +00002614#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002615#ifdef SVR4
2616#ifdef SYS_pgrpsys_subcall
2617 case SYS_pgrpsys:
2618 decode_subcall(tcp, SYS_pgrpsys_subcall,
2619 SYS_pgrpsys_nsubcalls, shift_style);
2620 break;
2621#endif /* SYS_pgrpsys_subcall */
2622#ifdef SYS_sigcall_subcall
2623 case SYS_sigcall:
2624 decode_subcall(tcp, SYS_sigcall_subcall,
2625 SYS_sigcall_nsubcalls, mask_style);
2626 break;
2627#endif /* SYS_sigcall_subcall */
2628 case SYS_msgsys:
2629 decode_subcall(tcp, SYS_msgsys_subcall,
2630 SYS_msgsys_nsubcalls, shift_style);
2631 break;
2632 case SYS_shmsys:
2633 decode_subcall(tcp, SYS_shmsys_subcall,
2634 SYS_shmsys_nsubcalls, shift_style);
2635 break;
2636 case SYS_semsys:
2637 decode_subcall(tcp, SYS_semsys_subcall,
2638 SYS_semsys_nsubcalls, shift_style);
2639 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002640 case SYS_sysfs:
2641 decode_subcall(tcp, SYS_sysfs_subcall,
2642 SYS_sysfs_nsubcalls, shift_style);
2643 break;
2644 case SYS_spcall:
2645 decode_subcall(tcp, SYS_spcall_subcall,
2646 SYS_spcall_nsubcalls, shift_style);
2647 break;
2648#ifdef SYS_context_subcall
2649 case SYS_context:
2650 decode_subcall(tcp, SYS_context_subcall,
2651 SYS_context_nsubcalls, shift_style);
2652 break;
2653#endif /* SYS_context_subcall */
Wichert Akkerman8829a551999-06-11 13:18:40 +00002654#ifdef SYS_door_subcall
2655 case SYS_door:
2656 decode_subcall(tcp, SYS_door_subcall,
2657 SYS_door_nsubcalls, door_style);
2658 break;
2659#endif /* SYS_door_subcall */
John Hughesbdf48f52001-03-06 15:08:09 +00002660#ifdef SYS_kaio_subcall
2661 case SYS_kaio:
2662 decode_subcall(tcp, SYS_kaio_subcall,
2663 SYS_kaio_nsubcalls, shift_style);
2664 break;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002665#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002666#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002667#ifdef FREEBSD
2668 case SYS_msgsys:
2669 case SYS_shmsys:
2670 case SYS_semsys:
2671 decode_subcall(tcp, 0, 0, table_style);
2672 break;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002673#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002674#ifdef SUNOS4
2675 case SYS_semsys:
2676 decode_subcall(tcp, SYS_semsys_subcall,
2677 SYS_semsys_nsubcalls, shift_style);
2678 break;
2679 case SYS_msgsys:
2680 decode_subcall(tcp, SYS_msgsys_subcall,
2681 SYS_msgsys_nsubcalls, shift_style);
2682 break;
2683 case SYS_shmsys:
2684 decode_subcall(tcp, SYS_shmsys_subcall,
2685 SYS_shmsys_nsubcalls, shift_style);
2686 break;
2687#endif
2688 }
2689
2690 internal_syscall(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002691 if (tcp->scno >=0 && tcp->scno < nsyscalls && !(qual_flags[tcp->scno] & QUAL_TRACE)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002692 tcp->flags |= TCB_INSYSCALL;
2693 return 0;
2694 }
2695
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002696 if (cflag == CFLAG_ONLY_STATS) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002697 tcp->flags |= TCB_INSYSCALL;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002698 gettimeofday(&tcp->etime, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002699 return 0;
2700 }
2701
2702 printleader(tcp);
2703 tcp->flags &= ~TCB_REPRINT;
2704 tcp_last = tcp;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002705 if (tcp->scno >= nsyscalls || tcp->scno < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002706 tprintf("syscall_%lu(", tcp->scno);
2707 else
2708 tprintf("%s(", sysent[tcp->scno].sys_name);
Roland McGrath761b5d72002-12-15 23:58:31 +00002709 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002710 ((qual_flags[tcp->scno] & QUAL_RAW) && tcp->scno != SYS_exit))
2711 sys_res = printargs(tcp);
2712 else
2713 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2714 if (fflush(tcp->outf) == EOF)
2715 return -1;
2716 tcp->flags |= TCB_INSYSCALL;
2717 /* Measure the entrance time as late as possible to avoid errors. */
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002718 if (dtime || cflag)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002719 gettimeofday(&tcp->etime, NULL);
2720 return sys_res;
2721}
2722
2723int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002724trace_syscall(struct tcb *tcp)
2725{
2726 return exiting(tcp) ?
2727 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2728}
2729
2730int
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002731printargs(tcp)
2732struct tcb *tcp;
2733{
2734 if (entering(tcp)) {
2735 int i;
2736
2737 for (i = 0; i < tcp->u_nargs; i++)
2738 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
2739 }
2740 return 0;
2741}
2742
2743long
2744getrval2(tcp)
2745struct tcb *tcp;
2746{
2747 long val = -1;
2748
2749#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002750#if defined (SPARC) || defined (SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04002751 struct pt_regs regs;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002752 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002753 return -1;
Mike Frysinger8566c502009-10-12 11:05:14 -04002754 val = regs.u_regs[U_REG_O1];
Roland McGrath6b1d43e2003-03-31 01:05:01 +00002755#elif defined(SH)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002756 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
Roland McGrath6b1d43e2003-03-31 01:05:01 +00002757 return -1;
Roland McGrathb4ce1762004-03-01 20:30:48 +00002758#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002759 if (upeek(tcp, PT_R9, &val) < 0)
Roland McGrathb4ce1762004-03-01 20:30:48 +00002760 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002761#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002762#endif /* LINUX */
2763
2764#ifdef SUNOS4
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002765 if (upeek(tcp, uoff(u_rval2), &val) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002766 return -1;
2767#endif /* SUNOS4 */
2768
2769#ifdef SVR4
2770#ifdef SPARC
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002771 val = tcp->status.PR_REG[R_O1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002772#endif /* SPARC */
2773#ifdef I386
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002774 val = tcp->status.PR_REG[EDX];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002775#endif /* I386 */
Michal Ludvig0e035502002-09-23 15:41:01 +00002776#ifdef X86_64
2777 val = tcp->status.PR_REG[RDX];
2778#endif /* X86_64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002779#ifdef MIPS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002780 val = tcp->status.PR_REG[CTX_V1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002781#endif /* MIPS */
2782#endif /* SVR4 */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002783
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002784#ifdef FREEBSD
2785 struct reg regs;
2786 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
2787 val = regs.r_edx;
Roland McGrath761b5d72002-12-15 23:58:31 +00002788#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002789 return val;
2790}
2791
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +00002792#ifdef SUNOS4
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002793/*
2794 * Apparently, indirect system calls have already be converted by ptrace(2),
2795 * so if you see "indir" this program has gone astray.
2796 */
2797int
2798sys_indir(tcp)
2799struct tcb *tcp;
2800{
2801 int i, scno, nargs;
2802
2803 if (entering(tcp)) {
2804 if ((scno = tcp->u_arg[0]) > nsyscalls) {
2805 fprintf(stderr, "Bogus syscall: %u\n", scno);
2806 return 0;
2807 }
2808 nargs = sysent[scno].nargs;
2809 tprintf("%s", sysent[scno].sys_name);
2810 for (i = 0; i < nargs; i++)
2811 tprintf(", %#lx", tcp->u_arg[i+1]);
2812 }
2813 return 0;
2814}
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +00002815#endif /* SUNOS4 */
Dmitry V. Levin2e55ff42008-09-03 01:02:46 +00002816
2817int
2818is_restart_error(struct tcb *tcp)
2819{
2820#ifdef LINUX
2821 if (!syserror(tcp))
2822 return 0;
2823 switch (tcp->u_error) {
2824 case ERESTARTSYS:
2825 case ERESTARTNOINTR:
2826 case ERESTARTNOHAND:
2827 case ERESTART_RESTARTBLOCK:
2828 return 1;
2829 default:
2830 break;
2831 }
2832#endif /* LINUX */
2833 return 0;
2834}