blob: 8fcd10bb315723365b306fda61560419fb9abf81 [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
112
Roland McGrathee36ce12004-09-04 03:53:10 +0000113static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000114#include "syscallent.h"
115};
Roland McGrathee36ce12004-09-04 03:53:10 +0000116static const int nsyscalls0 = sizeof sysent0 / sizeof sysent0[0];
Roland McGrath138c6a32006-01-12 09:50:49 +0000117int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118
119#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000120static const struct sysent sysent1[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121#include "syscallent1.h"
122};
Roland McGrathee36ce12004-09-04 03:53:10 +0000123static const int nsyscalls1 = sizeof sysent1 / sizeof sysent1[0];
Roland McGrath138c6a32006-01-12 09:50:49 +0000124int qual_flags1[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000125#endif /* SUPPORTED_PERSONALITIES >= 2 */
126
127#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000128static const struct sysent sysent2[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000129#include "syscallent2.h"
130};
Roland McGrathee36ce12004-09-04 03:53:10 +0000131static const int nsyscalls2 = sizeof sysent2 / sizeof sysent2[0];
Roland McGrath138c6a32006-01-12 09:50:49 +0000132int qual_flags2[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000133#endif /* SUPPORTED_PERSONALITIES >= 3 */
134
Roland McGrathee36ce12004-09-04 03:53:10 +0000135const struct sysent *sysent;
Roland McGrath138c6a32006-01-12 09:50:49 +0000136int *qual_flags;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000137int nsyscalls;
138
139/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000140#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000141#undef TF
142#undef TI
143#undef TN
144#undef TP
145#undef TS
146
Roland McGrathee36ce12004-09-04 03:53:10 +0000147static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000148#include "errnoent.h"
149};
Roland McGrathee36ce12004-09-04 03:53:10 +0000150static const int nerrnos0 = sizeof errnoent0 / sizeof errnoent0[0];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000151
152#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000153static const char *const errnoent1[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154#include "errnoent1.h"
155};
Roland McGrathee36ce12004-09-04 03:53:10 +0000156static const int nerrnos1 = sizeof errnoent1 / sizeof errnoent1[0];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000157#endif /* SUPPORTED_PERSONALITIES >= 2 */
158
159#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000160static const char *const errnoent2[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000161#include "errnoent2.h"
162};
Roland McGrathee36ce12004-09-04 03:53:10 +0000163static const int nerrnos2 = sizeof errnoent2 / sizeof errnoent2[0];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000164#endif /* SUPPORTED_PERSONALITIES >= 3 */
165
Roland McGrathee36ce12004-09-04 03:53:10 +0000166const char *const *errnoent;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000167int nerrnos;
168
169int current_personality;
170
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000171#ifndef PERSONALITY0_WORDSIZE
172# define PERSONALITY0_WORDSIZE sizeof(long)
173#endif
174const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
175 PERSONALITY0_WORDSIZE,
176#if SUPPORTED_PERSONALITIES > 1
177 PERSONALITY1_WORDSIZE,
178#endif
179#if SUPPORTED_PERSONALITIES > 2
180 PERSONALITY2_WORDSIZE,
181#endif
182};;
183
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000184int
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000185set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000186{
187 switch (personality) {
188 case 0:
189 errnoent = errnoent0;
190 nerrnos = nerrnos0;
191 sysent = sysent0;
192 nsyscalls = nsyscalls0;
193 ioctlent = ioctlent0;
194 nioctlents = nioctlents0;
195 signalent = signalent0;
196 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000197 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000198 break;
199
200#if SUPPORTED_PERSONALITIES >= 2
201 case 1:
202 errnoent = errnoent1;
203 nerrnos = nerrnos1;
204 sysent = sysent1;
205 nsyscalls = nsyscalls1;
206 ioctlent = ioctlent1;
207 nioctlents = nioctlents1;
208 signalent = signalent1;
209 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000210 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000211 break;
212#endif /* SUPPORTED_PERSONALITIES >= 2 */
213
214#if SUPPORTED_PERSONALITIES >= 3
215 case 2:
216 errnoent = errnoent2;
217 nerrnos = nerrnos2;
218 sysent = sysent2;
219 nsyscalls = nsyscalls2;
220 ioctlent = ioctlent2;
221 nioctlents = nioctlents2;
222 signalent = signalent2;
223 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000224 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000225 break;
226#endif /* SUPPORTED_PERSONALITIES >= 3 */
227
228 default:
229 return -1;
230 }
231
232 current_personality = personality;
233 return 0;
234}
235
Roland McGrathe10e62a2004-09-04 04:20:43 +0000236
Roland McGrath9797ceb2002-12-30 10:23:00 +0000237static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000238
Roland McGrathe10e62a2004-09-04 04:20:43 +0000239static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000240 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000241 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000242 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000243 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000244} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000245 { QUAL_TRACE, "trace", qual_syscall, "system call" },
246 { QUAL_TRACE, "t", qual_syscall, "system call" },
247 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
248 { QUAL_ABBREV, "a", qual_syscall, "system call" },
249 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
250 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
251 { QUAL_RAW, "raw", qual_syscall, "system call" },
252 { QUAL_RAW, "x", qual_syscall, "system call" },
253 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
254 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
255 { QUAL_SIGNAL, "s", qual_signal, "signal" },
256 { QUAL_FAULT, "fault", qual_fault, "fault" },
257 { QUAL_FAULT, "faults", qual_fault, "fault" },
258 { QUAL_FAULT, "m", qual_fault, "fault" },
259 { QUAL_READ, "read", qual_desc, "descriptor" },
260 { QUAL_READ, "reads", qual_desc, "descriptor" },
261 { QUAL_READ, "r", qual_desc, "descriptor" },
262 { QUAL_WRITE, "write", qual_desc, "descriptor" },
263 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
264 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000265 { 0, NULL, NULL, NULL },
266};
267
Roland McGrath9797ceb2002-12-30 10:23:00 +0000268static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000269qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000270{
Roland McGrath138c6a32006-01-12 09:50:49 +0000271 if (pers == 0 || pers < 0) {
272 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000273 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000274 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000275 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000276 }
277
278#if SUPPORTED_PERSONALITIES >= 2
279 if (pers == 1 || pers < 0) {
280 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000281 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000282 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000283 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000284 }
285#endif /* SUPPORTED_PERSONALITIES >= 2 */
286
287#if SUPPORTED_PERSONALITIES >= 3
288 if (pers == 2 || pers < 0) {
289 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000290 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000291 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000292 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000293 }
294#endif /* SUPPORTED_PERSONALITIES >= 3 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000295}
296
297static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000298qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000299{
300 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000301 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000302
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000303 if (isdigit((unsigned char)*s)) {
304 int i = atoi(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000305 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000306 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000307 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000308 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000309 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000310 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000311 if (strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000312 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000313 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000314 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000315
316#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000317 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000318 if (strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000319 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000320 rc = 0;
321 }
322#endif /* SUPPORTED_PERSONALITIES >= 2 */
323
324#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000325 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000326 if (strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000327 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000328 rc = 0;
329 }
330#endif /* SUPPORTED_PERSONALITIES >= 3 */
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000331
Roland McGrathfe6b3522005-02-02 04:40:11 +0000332 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000333}
334
335static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000336qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000337{
338 int i;
339 char buf[32];
340
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000341 if (isdigit((unsigned char)*s)) {
342 int signo = atoi(s);
343 if (signo < 0 || signo >= MAX_QUALS)
344 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000345 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000346 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000347 }
Roland McGrathd62b6712004-03-02 06:52:01 +0000348 if (strlen(s) >= sizeof buf)
Roland McGrathfe6b3522005-02-02 04:40:11 +0000349 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000350 strcpy(buf, s);
351 s = buf;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000352 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000353 s += 3;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000354 for (i = 0; i <= NSIG; i++)
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000355 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000356 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000357 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000358 }
Roland McGrath76421df2005-02-02 03:51:18 +0000359 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000360}
361
362static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000363qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000364{
365 return -1;
366}
367
368static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000369qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000370{
Roland McGrath48a035f2006-01-12 09:45:56 +0000371 if (isdigit((unsigned char)*s)) {
Roland McGrathfe6b3522005-02-02 04:40:11 +0000372 int desc = atoi(s);
373 if (desc < 0 || desc >= MAX_QUALS)
374 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000375 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000376 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000377 }
378 return -1;
379}
380
381static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000382lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000383{
384 if (strcmp(s, "file") == 0)
385 return TRACE_FILE;
386 if (strcmp(s, "ipc") == 0)
387 return TRACE_IPC;
388 if (strcmp(s, "network") == 0)
389 return TRACE_NETWORK;
390 if (strcmp(s, "process") == 0)
391 return TRACE_PROCESS;
392 if (strcmp(s, "signal") == 0)
393 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000394 if (strcmp(s, "desc") == 0)
395 return TRACE_DESC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000396 return -1;
397}
398
399void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000400qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000401{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000402 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000403 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000404 char *copy;
405 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000406 int i, n;
407
408 opt = &qual_options[0];
409 for (i = 0; (p = qual_options[i].option_name); i++) {
410 n = strlen(p);
411 if (strncmp(s, p, n) == 0 && s[n] == '=') {
412 opt = &qual_options[i];
413 s += n + 1;
414 break;
415 }
416 }
417 not = 0;
418 if (*s == '!') {
419 not = 1;
420 s++;
421 }
422 if (strcmp(s, "none") == 0) {
423 not = 1 - not;
424 s = "all";
425 }
426 if (strcmp(s, "all") == 0) {
427 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000428 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000429 }
430 return;
431 }
432 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000433 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000434 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000435 if (!(copy = strdup(s))) {
436 fprintf(stderr, "out of memory\n");
437 exit(1);
438 }
439 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000440 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000441 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000442 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000443 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000444
445#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000446 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000447 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000448 qualify_one(i, opt->bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000449#endif /* SUPPORTED_PERSONALITIES >= 2 */
450
451#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000452 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000453 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000454 qualify_one(i, opt->bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000455#endif /* SUPPORTED_PERSONALITIES >= 3 */
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000456
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000457 continue;
458 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000459 if (opt->qualify(p, opt->bitflag, not)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000460 fprintf(stderr, "strace: invalid %s `%s'\n",
461 opt->argument_name, p);
462 exit(1);
463 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000464 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000465 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000466 return;
467}
468
469static void
470dumpio(tcp)
471struct tcb *tcp;
472{
473 if (syserror(tcp))
474 return;
475 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
476 return;
Roland McGrath17352792005-06-07 23:21:26 +0000477 switch (known_scno(tcp)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000478 case SYS_read:
Roland McGrathaa510622004-08-31 07:47:45 +0000479#ifdef SYS_pread64
480 case SYS_pread64:
481#endif
482#if defined SYS_pread && SYS_pread64 != SYS_pread
483 case SYS_pread:
484#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000485#ifdef SYS_recv
486 case SYS_recv:
Roland McGrath17352792005-06-07 23:21:26 +0000487#elif defined SYS_sub_recv
488 case SYS_sub_recv:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000489#endif
490#ifdef SYS_recvfrom
491 case SYS_recvfrom:
Roland McGrath17352792005-06-07 23:21:26 +0000492#elif defined SYS_sub_recvfrom
493 case SYS_sub_recvfrom:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000494#endif
495 if (qual_flags[tcp->u_arg[0]] & QUAL_READ)
496 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
497 break;
498 case SYS_write:
Roland McGrathaa510622004-08-31 07:47:45 +0000499#ifdef SYS_pwrite64
500 case SYS_pwrite64:
501#endif
502#if defined SYS_pwrite && SYS_pwrite64 != SYS_pwrite
503 case SYS_pwrite:
504#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000505#ifdef SYS_send
506 case SYS_send:
Roland McGrath17352792005-06-07 23:21:26 +0000507#elif defined SYS_sub_send
508 case SYS_sub_send:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000509#endif
510#ifdef SYS_sendto
511 case SYS_sendto:
Roland McGrath17352792005-06-07 23:21:26 +0000512#elif defined SYS_sub_sendto
513 case SYS_sub_sendto:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000514#endif
515 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE)
516 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
517 break;
John Hughes1d08dcf2001-07-10 13:48:44 +0000518#ifdef SYS_readv
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000519 case SYS_readv:
520 if (qual_flags[tcp->u_arg[0]] & QUAL_READ)
521 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
522 break;
John Hughes1d08dcf2001-07-10 13:48:44 +0000523#endif
524#ifdef SYS_writev
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000525 case SYS_writev:
526 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE)
527 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
528 break;
John Hughes1d08dcf2001-07-10 13:48:44 +0000529#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000530 }
531}
532
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000533#ifndef FREEBSD
Wichert Akkerman8829a551999-06-11 13:18:40 +0000534enum subcall_style { shift_style, deref_style, mask_style, door_style };
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000535#else /* FREEBSD */
536enum subcall_style { shift_style, deref_style, mask_style, door_style, table_style };
537
538struct subcall {
539 int call;
540 int nsubcalls;
541 int subcalls[5];
542};
543
Roland McGratha4d48532005-06-08 20:45:28 +0000544static const struct subcall subcalls_table[] = {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000545 { SYS_shmsys, 5, { SYS_shmat, SYS_shmctl, SYS_shmdt, SYS_shmget, SYS_shmctl } },
John Hughes61eeb552001-03-06 15:51:53 +0000546#ifdef SYS_semconfig
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000547 { SYS_semsys, 4, { SYS___semctl, SYS_semget, SYS_semop, SYS_semconfig } },
John Hughes61eeb552001-03-06 15:51:53 +0000548#else
549 { SYS_semsys, 3, { SYS___semctl, SYS_semget, SYS_semop } },
550#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000551 { SYS_msgsys, 4, { SYS_msgctl, SYS_msgget, SYS_msgsnd, SYS_msgrcv } },
552};
553#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000554
Denys Vlasenko8ba1cd72008-12-30 17:50:46 +0000555#if !(defined(LINUX) && ( defined(ALPHA) || defined(MIPS) || defined(__ARM_EABI__) ))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000556
Roland McGratha4d48532005-06-08 20:45:28 +0000557static void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000558decode_subcall(tcp, subcall, nsubcalls, style)
559struct tcb *tcp;
560int subcall;
561int nsubcalls;
562enum subcall_style style;
563{
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000564 unsigned long addr, mask;
Michal Ludvig10a88d02002-10-07 14:31:00 +0000565 int i;
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000566 int size = personality_wordsize[current_personality];
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000567
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000568 switch (style) {
569 case shift_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000570 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
571 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000572 tcp->scno = subcall + tcp->u_arg[0];
573 if (sysent[tcp->scno].nargs != -1)
574 tcp->u_nargs = sysent[tcp->scno].nargs;
575 else
576 tcp->u_nargs--;
577 for (i = 0; i < tcp->u_nargs; i++)
578 tcp->u_arg[i] = tcp->u_arg[i + 1];
579 break;
580 case deref_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000581 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
582 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000583 tcp->scno = subcall + tcp->u_arg[0];
584 addr = tcp->u_arg[1];
585 for (i = 0; i < sysent[tcp->scno].nargs; i++) {
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000586 if (size == sizeof(int)) {
587 unsigned int arg;
588 if (umove(tcp, addr, &arg) < 0)
589 arg = 0;
590 tcp->u_arg[i] = arg;
591 }
592 else if (size == sizeof(long)) {
593 unsigned long arg;
594 if (umove(tcp, addr, &arg) < 0)
595 arg = 0;
596 tcp->u_arg[i] = arg;
597 }
598 else
599 abort();
600 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000601 }
602 tcp->u_nargs = sysent[tcp->scno].nargs;
603 break;
604 case mask_style:
605 mask = (tcp->u_arg[0] >> 8) & 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000606 for (i = 0; mask; i++)
607 mask >>= 1;
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000608 if (i >= nsubcalls)
609 return;
610 tcp->u_arg[0] &= 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000611 tcp->scno = subcall + i;
612 if (sysent[tcp->scno].nargs != -1)
613 tcp->u_nargs = sysent[tcp->scno].nargs;
614 break;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000615 case door_style:
616 /*
617 * Oh, yuck. The call code is the *sixth* argument.
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000618 * (don't you mean the *last* argument? - JH)
Wichert Akkerman8829a551999-06-11 13:18:40 +0000619 */
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000620 if (tcp->u_arg[5] < 0 || tcp->u_arg[5] >= nsubcalls)
621 return;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000622 tcp->scno = subcall + tcp->u_arg[5];
623 if (sysent[tcp->scno].nargs != -1)
624 tcp->u_nargs = sysent[tcp->scno].nargs;
625 else
626 tcp->u_nargs--;
627 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000628#ifdef FREEBSD
629 case table_style:
630 for (i = 0; i < sizeof(subcalls_table) / sizeof(struct subcall); i++)
631 if (subcalls_table[i].call == tcp->scno) break;
632 if (i < sizeof(subcalls_table) / sizeof(struct subcall) &&
633 tcp->u_arg[0] >= 0 && tcp->u_arg[0] < subcalls_table[i].nsubcalls) {
634 tcp->scno = subcalls_table[i].subcalls[tcp->u_arg[0]];
635 for (i = 0; i < tcp->u_nargs; i++)
636 tcp->u_arg[i] = tcp->u_arg[i + 1];
637 }
638 break;
639#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000640 }
641}
642#endif
643
644struct tcb *tcp_last = NULL;
645
646static int
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000647internal_syscall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000648{
649 /*
650 * We must always trace a few critical system calls in order to
651 * correctly support following forks in the presence of tracing
652 * qualifiers.
653 */
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000654 int (*func)();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000655
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000656 if (tcp->scno < 0 || tcp->scno >= nsyscalls)
657 return 0;
658
659 func = sysent[tcp->scno].sys_func;
660
661 if (sys_exit == func)
662 return internal_exit(tcp);
663
664 if ( sys_fork == func
665#if defined(FREEBSD) || defined(LINUX) || defined(SUNOS4)
666 || sys_vfork == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000667#endif
Dmitry V. Levin257e1572009-12-26 17:55:24 +0000668#ifdef LINUX
669 || sys_clone == func
670#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000671#if UNIXWARE > 2
672 || sys_rfork == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000673#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000674 )
675 return internal_fork(tcp);
676
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000677 if ( sys_execve == func
678#if defined(SPARC) || defined(SPARC64) || defined(SUNOS4)
679 || sys_execv == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000680#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000681#if UNIXWARE > 2
682 || sys_rexecve == func
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000683#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000684 )
685 return internal_exec(tcp);
686
687 if ( sys_waitpid == func
688 || sys_wait4 == func
689#if defined(SVR4) || defined(FREEBSD) || defined(SUNOS4)
690 || sys_wait == func
Roland McGrath923f7502003-01-09 06:53:27 +0000691#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000692#ifdef ALPHA
693 || sys_osf_wait4 == func
Roland McGrath08267b82004-02-20 22:56:43 +0000694#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000695 )
696 return internal_wait(tcp, 2);
697
698#if defined(LINUX) || defined(SVR4)
699 if (sys_waitid == func)
700 return internal_wait(tcp, 3);
701#endif
702
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000703 return 0;
704}
705
Wichert Akkermanc7926982000-04-10 22:22:31 +0000706
707#ifdef LINUX
708#if defined (I386)
709 static long eax;
710#elif defined (IA64)
711 long r8, r10, psr;
712 long ia32 = 0;
713#elif defined (POWERPC)
714 static long result,flags;
715#elif defined (M68K)
Andreas Schwabffca9e32010-05-28 20:53:14 +0200716 static long d0;
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000717#elif defined(BFIN)
718 static long r0;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000719#elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +0000720 static struct pt_regs regs;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000721#elif defined (ALPHA)
722 static long r0;
723 static long a3;
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000724#elif defined(AVR32)
725 static struct pt_regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000726#elif defined (SPARC) || defined (SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -0400727 static struct pt_regs regs;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000728 static unsigned long trap;
Roland McGrath542c2c62008-05-20 01:11:56 +0000729#elif defined(LINUX_MIPSN32)
730 static long long a3;
731 static long long r2;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000732#elif defined(MIPS)
733 static long a3;
734 static long r2;
Michal Ludvig10a88d02002-10-07 14:31:00 +0000735#elif defined(S390) || defined(S390X)
Wichert Akkermanc7926982000-04-10 22:22:31 +0000736 static long gpr2;
737 static long pc;
Michal Ludvig882eda82002-11-11 12:50:47 +0000738 static long syscall_mode;
Wichert Akkermanc1652e22001-03-27 12:17:16 +0000739#elif defined(HPPA)
740 static long r28;
Wichert Akkermanccef6372002-05-01 16:39:22 +0000741#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000742 static long r0;
Roland McGrathf5a47772003-06-26 22:40:42 +0000743#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000744 static long r9;
Michal Ludvig0e035502002-09-23 15:41:01 +0000745#elif defined(X86_64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000746 static long rax;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000747#elif defined(CRISV10) || defined(CRISV32)
748 static long r10;
Edgar E. Iglesias939caba2010-07-06 14:21:07 +0200749#elif defined(MICROBLAZE)
750 static long r3;
Roland McGrath761b5d72002-12-15 23:58:31 +0000751#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000752#endif /* LINUX */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000753#ifdef FREEBSD
754 struct reg regs;
Roland McGrath761b5d72002-12-15 23:58:31 +0000755#endif /* FREEBSD */
Wichert Akkermanc7926982000-04-10 22:22:31 +0000756
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000757int
Denys Vlasenkofb036672009-01-23 16:30:26 +0000758get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000759{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000760 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000761
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000762#ifdef LINUX
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000763# if defined(S390) || defined(S390X)
Roland McGrath96dc5142003-01-20 10:23:04 +0000764 if (tcp->flags & TCB_WAITEXECVE) {
765 /*
766 * When the execve system call completes successfully, the
767 * new process still has -ENOSYS (old style) or __NR_execve
768 * (new style) in gpr2. We cannot recover the scno again
769 * by disassembly, because the image that executed the
770 * syscall is gone now. Fortunately, we don't want it. We
771 * leave the flag set so that syscall_fixup can fake the
772 * result.
773 */
774 if (tcp->flags & TCB_INSYSCALL)
775 return 1;
776 /*
777 * This is the SIGTRAP after execve. We cannot try to read
778 * the system call here either.
779 */
780 tcp->flags &= ~TCB_WAITEXECVE;
781 return 0;
782 }
Roland McGrath2f924ca2003-06-26 22:23:28 +0000783
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000784 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Roland McGrath2f924ca2003-06-26 22:23:28 +0000785 return -1;
786
787 if (syscall_mode != -ENOSYS) {
788 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000789 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000790 */
791 scno = syscall_mode;
792 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000793 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000794 * Old style of "passing" the scno via the SVC instruction.
795 */
796
797 long opcode, offset_reg, tmp;
798 void * svc_addr;
799 int gpr_offset[16] = {PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
800 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
801 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
802 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15};
Roland McGrath761b5d72002-12-15 23:58:31 +0000803
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000804 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000805 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000806 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000807 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000808 if (errno) {
809 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000810 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000811 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000812
813 /*
814 * We have to check if the SVC got executed directly or via an
815 * EXECUTE instruction. In case of EXECUTE it is necessary to do
816 * instruction decoding to derive the system call number.
817 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
818 * so that this doesn't work if a SVC opcode is part of an EXECUTE
819 * opcode. Since there is no way to find out the opcode size this
820 * is the best we can do...
821 */
822
823 if ((opcode & 0xff00) == 0x0a00) {
824 /* SVC opcode */
825 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000826 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000827 else {
828 /* SVC got executed by EXECUTE instruction */
829
830 /*
831 * Do instruction decoding of EXECUTE. If you really want to
832 * understand this, read the Principles of Operations.
833 */
834 svc_addr = (void *) (opcode & 0xfff);
835
836 tmp = 0;
837 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000838 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000839 return -1;
840 svc_addr += tmp;
841
842 tmp = 0;
843 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000844 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000845 return -1;
846 svc_addr += tmp;
847
Denys Vlasenkofb036672009-01-23 16:30:26 +0000848 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000849 if (errno)
850 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000851# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000852 scno >>= 48;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000853# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000854 scno >>= 16;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000855# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000856 tmp = 0;
857 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000858 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000859 return -1;
860
861 scno = (scno | tmp) & 0xff;
862 }
863 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000864# elif defined (POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000865 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000866 return -1;
867 if (!(tcp->flags & TCB_INSYSCALL)) {
868 /* Check if we return from execve. */
869 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
870 tcp->flags &= ~TCB_WAITEXECVE;
871 return 0;
872 }
873 }
Andreas Schwabd69fa492010-07-12 21:39:57 +0200874
875# ifdef POWERPC64
876 if (!(tcp->flags & TCB_INSYSCALL)) {
877 static int currpers = -1;
878 long val;
879 int pid = tcp->pid;
880
881 /* Check for 64/32 bit mode. */
882 if (upeek(tcp, sizeof (unsigned long)*PT_MSR, &val) < 0)
883 return -1;
884 /* SF is bit 0 of MSR */
885 if (val < 0)
886 currpers = 0;
887 else
888 currpers = 1;
889 if (currpers != current_personality) {
890 static const char *const names[] = {"64 bit", "32 bit"};
891 set_personality(currpers);
Dmitry V. Levinbdafa1a2010-12-02 23:38:13 +0000892 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
Andreas Schwabd69fa492010-07-12 21:39:57 +0200893 pid, names[current_personality]);
894 }
895 }
896# endif
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000897# elif defined(AVR32)
898 /*
899 * Read complete register set in one go.
900 */
901 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
902 return -1;
903
904 /*
905 * We only need to grab the syscall number on syscall entry.
906 */
907 if (!(tcp->flags & TCB_INSYSCALL)) {
908 scno = regs.r8;
909
910 /* Check if we return from execve. */
911 if (tcp->flags & TCB_WAITEXECVE) {
912 tcp->flags &= ~TCB_WAITEXECVE;
913 return 0;
914 }
915 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000916# elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000917 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000918 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000919# elif defined (I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000920 if (upeek(tcp, 4*ORIG_EAX, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000921 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000922# elif defined (X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000923 if (upeek(tcp, 8*ORIG_RAX, &scno) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +0000924 return -1;
925
Roland McGrath761b5d72002-12-15 23:58:31 +0000926 if (!(tcp->flags & TCB_INSYSCALL)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000927 static int currpers = -1;
Michal Ludvig0e035502002-09-23 15:41:01 +0000928 long val;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000929 int pid = tcp->pid;
Michal Ludvig0e035502002-09-23 15:41:01 +0000930
931 /* Check CS register value. On x86-64 linux it is:
932 * 0x33 for long mode (64 bit)
933 * 0x23 for compatibility mode (32 bit)
Roland McGrath761b5d72002-12-15 23:58:31 +0000934 * It takes only one ptrace and thus doesn't need
Michal Ludvig0e035502002-09-23 15:41:01 +0000935 * to be cached.
936 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000937 if (upeek(tcp, 8*CS, &val) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +0000938 return -1;
Denys Vlasenko8236f252009-01-02 18:10:08 +0000939 switch (val) {
Michal Ludvig0e035502002-09-23 15:41:01 +0000940 case 0x23: currpers = 1; break;
941 case 0x33: currpers = 0; break;
942 default:
943 fprintf(stderr, "Unknown value CS=0x%02X while "
944 "detecting personality of process "
945 "PID=%d\n", (int)val, pid);
946 currpers = current_personality;
947 break;
948 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000949# if 0
Michal Ludvig0e035502002-09-23 15:41:01 +0000950 /* This version analyzes the opcode of a syscall instruction.
951 * (int 0x80 on i386 vs. syscall on x86-64)
952 * It works, but is too complicated.
953 */
954 unsigned long val, rip, i;
955
Denys Vlasenko8236f252009-01-02 18:10:08 +0000956 if (upeek(tcp, 8*RIP, &rip) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +0000957 perror("upeek(RIP)");
Roland McGrath761b5d72002-12-15 23:58:31 +0000958
Michal Ludvig0e035502002-09-23 15:41:01 +0000959 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
Denys Vlasenko8236f252009-01-02 18:10:08 +0000960 rip -= 2;
Michal Ludvig0e035502002-09-23 15:41:01 +0000961 errno = 0;
962
Denys Vlasenko8236f252009-01-02 18:10:08 +0000963 call = ptrace(PTRACE_PEEKTEXT, pid, (char *)rip, (char *)0);
Roland McGrath761b5d72002-12-15 23:58:31 +0000964 if (errno)
Dmitry V. Levinbdafa1a2010-12-02 23:38:13 +0000965 fprintf(stderr, "ptrace_peektext failed: %s\n",
Michal Ludvig0e035502002-09-23 15:41:01 +0000966 strerror(errno));
Denys Vlasenko8236f252009-01-02 18:10:08 +0000967 switch (call & 0xffff) {
Michal Ludvig0e035502002-09-23 15:41:01 +0000968 /* x86-64: syscall = 0x0f 0x05 */
969 case 0x050f: currpers = 0; break;
970 /* i386: int 0x80 = 0xcd 0x80 */
971 case 0x80cd: currpers = 1; break;
972 default:
973 currpers = current_personality;
Roland McGrath761b5d72002-12-15 23:58:31 +0000974 fprintf(stderr,
Michal Ludvig0e035502002-09-23 15:41:01 +0000975 "Unknown syscall opcode (0x%04X) while "
976 "detecting personality of process "
977 "PID=%d\n", (int)call, pid);
978 break;
979 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000980# endif
Denys Vlasenko8236f252009-01-02 18:10:08 +0000981 if (currpers != current_personality) {
982 static const char *const names[] = {"64 bit", "32 bit"};
Michal Ludvig0e035502002-09-23 15:41:01 +0000983 set_personality(currpers);
Dmitry V. Levinbdafa1a2010-12-02 23:38:13 +0000984 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
Michal Ludvig0e035502002-09-23 15:41:01 +0000985 pid, names[current_personality]);
986 }
Roland McGrath761b5d72002-12-15 23:58:31 +0000987 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000988# elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000989# define IA64_PSR_IS ((long)1 << 34)
Roland McGratheb9e2e82009-06-02 16:49:22 -0700990 if (upeek (tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000991 ia32 = (psr & IA64_PSR_IS) != 0;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000992 if (!(tcp->flags & TCB_INSYSCALL)) {
993 if (ia32) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000994 if (upeek(tcp, PT_R1, &scno) < 0) /* orig eax */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000995 return -1;
996 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700997 if (upeek (tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000998 return -1;
999 }
Roland McGrathba954762003-03-05 06:29:06 +00001000 /* Check if we return from execve. */
1001 if (tcp->flags & TCB_WAITEXECVE) {
1002 tcp->flags &= ~TCB_WAITEXECVE;
1003 return 0;
1004 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001005 } else {
1006 /* syscall in progress */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001007 if (upeek (tcp, PT_R8, &r8) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001008 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001009 if (upeek (tcp, PT_R10, &r10) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001010 return -1;
1011 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001012# elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001013 /*
1014 * Read complete register set in one go.
1015 */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001016 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +00001017 return -1;
1018
1019 /*
1020 * We only need to grab the syscall number on syscall entry.
1021 */
1022 if (regs.ARM_ip == 0) {
Roland McGrath9bc63402007-11-01 21:42:18 +00001023 if (!(tcp->flags & TCB_INSYSCALL)) {
1024 /* Check if we return from execve. */
1025 if (tcp->flags & TCB_WAITEXECVE) {
1026 tcp->flags &= ~TCB_WAITEXECVE;
1027 return 0;
1028 }
1029 }
1030
Roland McGrath0f87c492003-06-03 23:29:04 +00001031 /*
1032 * Note: we only deal with only 32-bit CPUs here.
1033 */
1034 if (regs.ARM_cpsr & 0x20) {
1035 /*
1036 * Get the Thumb-mode system call number
1037 */
1038 scno = regs.ARM_r7;
1039 } else {
1040 /*
1041 * Get the ARM-mode system call number
1042 */
1043 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +00001044 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +00001045 if (errno)
1046 return -1;
1047
1048 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
1049 tcp->flags &= ~TCB_WAITEXECVE;
1050 return 0;
1051 }
1052
Roland McGrathf691bd22006-04-25 07:34:41 +00001053 /* Handle the EABI syscall convention. We do not
1054 bother converting structures between the two
1055 ABIs, but basic functionality should work even
1056 if strace and the traced program have different
1057 ABIs. */
1058 if (scno == 0xef000000) {
1059 scno = regs.ARM_r7;
1060 } else {
1061 if ((scno & 0x0ff00000) != 0x0f900000) {
1062 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1063 scno);
1064 return -1;
1065 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001066
Roland McGrathf691bd22006-04-25 07:34:41 +00001067 /*
1068 * Fixup the syscall number
1069 */
1070 scno &= 0x000fffff;
1071 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001072 }
Roland McGrath56703312008-05-20 01:35:55 +00001073 if (scno & 0x0f0000) {
1074 /*
1075 * Handle ARM specific syscall
1076 */
1077 set_personality(1);
1078 scno &= 0x0000ffff;
1079 } else
1080 set_personality(0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001081
1082 if (tcp->flags & TCB_INSYSCALL) {
1083 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1084 tcp->flags &= ~TCB_INSYSCALL;
1085 }
1086 } else {
1087 if (!(tcp->flags & TCB_INSYSCALL)) {
1088 fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
1089 tcp->flags |= TCB_INSYSCALL;
1090 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001091 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001092# elif defined (M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001093 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001094 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001095# elif defined (LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001096 unsigned long long regs[38];
1097
Roland McGratheb9e2e82009-06-02 16:49:22 -07001098 if (ptrace (PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001099 return -1;
1100 a3 = regs[REG_A3];
1101 r2 = regs[REG_V0];
1102
1103 if(!(tcp->flags & TCB_INSYSCALL)) {
1104 scno = r2;
1105
1106 /* Check if we return from execve. */
1107 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1108 tcp->flags &= ~TCB_WAITEXECVE;
1109 return 0;
1110 }
1111
1112 if (scno < 0 || scno > nsyscalls) {
1113 if(a3 == 0 || a3 == -1) {
1114 if(debug)
1115 fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
1116 return 0;
1117 }
1118 }
1119 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001120# elif defined (MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001121 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001122 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001123 if(!(tcp->flags & TCB_INSYSCALL)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001124 if (upeek(tcp, REG_V0, &scno) < 0)
1125 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001126
Roland McGrath542c2c62008-05-20 01:11:56 +00001127 /* Check if we return from execve. */
1128 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1129 tcp->flags &= ~TCB_WAITEXECVE;
1130 return 0;
1131 }
1132
Wichert Akkermanf90da011999-10-31 21:15:38 +00001133 if (scno < 0 || scno > nsyscalls) {
1134 if(a3 == 0 || a3 == -1) {
1135 if(debug)
1136 fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
1137 return 0;
1138 }
1139 }
1140 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001141 if (upeek(tcp, REG_V0, &r2) < 0)
1142 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001143 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001144# elif defined (ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001145 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001146 return -1;
1147
1148 if (!(tcp->flags & TCB_INSYSCALL)) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001149 if (upeek(tcp, REG_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001150 return -1;
1151
1152 /* Check if we return from execve. */
1153 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1154 tcp->flags &= ~TCB_WAITEXECVE;
1155 return 0;
1156 }
1157
1158 /*
1159 * Do some sanity checks to figure out if it's
1160 * really a syscall entry
1161 */
1162 if (scno < 0 || scno > nsyscalls) {
1163 if (a3 == 0 || a3 == -1) {
1164 if (debug)
1165 fprintf (stderr, "stray syscall exit: r0 = %ld\n", scno);
1166 return 0;
1167 }
1168 }
1169 }
1170 else {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001171 if (upeek(tcp, REG_R0, &r0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001172 return -1;
1173 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001174# elif defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001176 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001177 return -1;
1178
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001179 /* If we are entering, then disassemble the syscall trap. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001180 if (!(tcp->flags & TCB_INSYSCALL)) {
1181 /* Retrieve the syscall trap instruction. */
1182 errno = 0;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001183# if defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001184 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001185 trap >>= 32;
Mike Frysinger8566c502009-10-12 11:05:14 -04001186# else
1187 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001188# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001189 if (errno)
1190 return -1;
1191
1192 /* Disassemble the trap to see what personality to use. */
1193 switch (trap) {
1194 case 0x91d02010:
1195 /* Linux/SPARC syscall trap. */
1196 set_personality(0);
1197 break;
Wichert Akkermandacfb6e1999-06-03 14:21:07 +00001198 case 0x91d0206d:
1199 /* Linux/SPARC64 syscall trap. */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001200 set_personality(2);
1201 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001202 case 0x91d02000:
1203 /* SunOS syscall trap. (pers 1) */
1204 fprintf(stderr,"syscall: SunOS no support\n");
1205 return -1;
1206 case 0x91d02008:
1207 /* Solaris 2.x syscall trap. (per 2) */
1208 set_personality(1);
Roland McGrath761b5d72002-12-15 23:58:31 +00001209 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001210 case 0x91d02009:
1211 /* NetBSD/FreeBSD syscall trap. */
1212 fprintf(stderr,"syscall: NetBSD/FreeBSD not supported\n");
1213 return -1;
1214 case 0x91d02027:
1215 /* Solaris 2.x gettimeofday */
1216 set_personality(1);
1217 break;
1218 default:
1219 /* Unknown syscall trap. */
1220 if(tcp->flags & TCB_WAITEXECVE) {
1221 tcp->flags &= ~TCB_WAITEXECVE;
1222 return 0;
1223 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001224# if defined (SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001225 fprintf(stderr,"syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001226# else
Mike Frysinger8566c502009-10-12 11:05:14 -04001227 fprintf(stderr,"syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001228# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001229 return -1;
1230 }
1231
1232 /* Extract the system call number from the registers. */
1233 if (trap == 0x91d02027)
1234 scno = 156;
1235 else
Mike Frysinger8566c502009-10-12 11:05:14 -04001236 scno = regs.u_regs[U_REG_G1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001237 if (scno == 0) {
Mike Frysinger8566c502009-10-12 11:05:14 -04001238 scno = regs.u_regs[U_REG_O0];
1239 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 +00001240 }
1241 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001242# elif defined(HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001243 if (upeek(tcp, PT_GR20, &scno) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001244 return -1;
1245 if (!(tcp->flags & TCB_INSYSCALL)) {
1246 /* Check if we return from execve. */
1247 if ((tcp->flags & TCB_WAITEXECVE)) {
1248 tcp->flags &= ~TCB_WAITEXECVE;
1249 return 0;
1250 }
1251 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001252# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001253 /*
1254 * In the new syscall ABI, the system call number is in R3.
1255 */
1256 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1257 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001258
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001259 if (scno < 0) {
1260 /* Odd as it may seem, a glibc bug has been known to cause
1261 glibc to issue bogus negative syscall numbers. So for
1262 our purposes, make strace print what it *should* have been */
1263 long correct_scno = (scno & 0xff);
1264 if (debug)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001265 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001266 "Detected glibc bug: bogus system call"
1267 " number = %ld, correcting to %ld\n",
1268 scno,
1269 correct_scno);
1270 scno = correct_scno;
1271 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00001272
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001273 if (!(tcp->flags & TCB_INSYSCALL)) {
1274 /* Check if we return from execve. */
1275 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1276 tcp->flags &= ~TCB_WAITEXECVE;
1277 return 0;
1278 }
1279 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001280# elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001281 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001282 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001283 scno &= 0xFFFF;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001284
1285 if (!(tcp->flags & TCB_INSYSCALL)) {
1286 /* Check if we return from execve. */
1287 if (tcp->flags & TCB_WAITEXECVE) {
1288 tcp->flags &= ~TCB_WAITEXECVE;
1289 return 0;
1290 }
1291 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001292# elif defined(CRISV10) || defined(CRISV32)
1293 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1294 return -1;
Chris Metcalfc8c66982009-12-28 10:00:15 -05001295# elif defined(TILE)
1296 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1297 return -1;
1298
1299 if (!(tcp->flags & TCB_INSYSCALL)) {
1300 /* Check if we return from execve. */
1301 if (tcp->flags & TCB_WAITEXECVE) {
1302 tcp->flags &= ~TCB_WAITEXECVE;
1303 return 0;
1304 }
1305 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001306# elif defined(MICROBLAZE)
1307 if (upeek(tcp, 0, &scno) < 0)
1308 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001309# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001310#endif /* LINUX */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001311
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001312#ifdef SUNOS4
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001313 if (upeek(tcp, uoff(u_arg[7]), &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001314 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001315#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001316 /* new syscall ABI returns result in R0 */
1317 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1318 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001319#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001320 /* ABI defines result returned in r9 */
1321 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1322 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001323#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001324
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001325#ifdef USE_PROCFS
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001326# ifdef HAVE_PR_SYSCALL
John Hughes25299712001-03-06 10:10:06 +00001327 scno = tcp->status.PR_SYSCALL;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001328# else
1329# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001330 scno = tcp->status.PR_WHAT;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001331# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001332 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001333 perror("pread");
1334 return -1;
1335 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001336 switch (regs.r_eax) {
1337 case SYS_syscall:
1338 case SYS___syscall:
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001339 pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int));
1340 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001341 default:
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001342 scno = regs.r_eax;
1343 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001344 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001345# endif /* FREEBSD */
1346# endif /* !HAVE_PR_SYSCALL */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001347#endif /* USE_PROCFS */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001348
Wichert Akkerman5ae21ea2000-05-01 01:53:59 +00001349 if (!(tcp->flags & TCB_INSYSCALL))
1350 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001351 return 1;
1352}
1353
Pavel Machek4dc3b142000-02-01 17:58:41 +00001354
Roland McGrath17352792005-06-07 23:21:26 +00001355long
1356known_scno(tcp)
1357struct tcb *tcp;
1358{
1359 long scno = tcp->scno;
1360 if (scno >= 0 && scno < nsyscalls && sysent[scno].native_scno != 0)
1361 scno = sysent[scno].native_scno;
1362 else
1363 scno += NR_SYSCALL_BASE;
1364 return scno;
1365}
1366
Roland McGratheb9e2e82009-06-02 16:49:22 -07001367/* Called in trace_syscall() at each syscall entry and exit.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001368 * Returns:
Roland McGratheb9e2e82009-06-02 16:49:22 -07001369 * 0: "ignore this syscall", bail out of trace_syscall() silently.
1370 * 1: ok, continue in trace_syscall().
1371 * other: error, trace_syscall() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001372 * ("????" etc) and bail out.
1373 */
Roland McGratha4d48532005-06-08 20:45:28 +00001374static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001375syscall_fixup(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001376{
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001377#ifdef USE_PROCFS
Roland McGrath17352792005-06-07 23:21:26 +00001378 int scno = known_scno(tcp);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001379
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001380 if (!(tcp->flags & TCB_INSYSCALL)) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001381 if (tcp->status.PR_WHY != PR_SYSENTRY) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001382 if (
1383 scno == SYS_fork
1384#ifdef SYS_vfork
1385 || scno == SYS_vfork
1386#endif /* SYS_vfork */
John Hughes4e36a812001-04-18 15:11:51 +00001387#ifdef SYS_fork1
1388 || scno == SYS_fork1
1389#endif /* SYS_fork1 */
1390#ifdef SYS_forkall
1391 || scno == SYS_forkall
1392#endif /* SYS_forkall */
1393#ifdef SYS_rfork1
1394 || scno == SYS_rfork1
1395#endif /* SYS_fork1 */
1396#ifdef SYS_rforkall
1397 || scno == SYS_rforkall
1398#endif /* SYS_rforkall */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001399 ) {
1400 /* We are returning in the child, fake it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001401 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001402 trace_syscall(tcp);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001403 tcp->status.PR_WHY = PR_SYSEXIT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001404 }
1405 else {
1406 fprintf(stderr, "syscall: missing entry\n");
1407 tcp->flags |= TCB_INSYSCALL;
1408 }
1409 }
1410 }
1411 else {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001412 if (tcp->status.PR_WHY != PR_SYSEXIT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001413 fprintf(stderr, "syscall: missing exit\n");
1414 tcp->flags &= ~TCB_INSYSCALL;
1415 }
1416 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001417#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001418#ifdef SUNOS4
1419 if (!(tcp->flags & TCB_INSYSCALL)) {
1420 if (scno == 0) {
1421 fprintf(stderr, "syscall: missing entry\n");
1422 tcp->flags |= TCB_INSYSCALL;
1423 }
1424 }
1425 else {
1426 if (scno != 0) {
1427 if (debug) {
1428 /*
1429 * This happens when a signal handler
1430 * for a signal which interrupted a
1431 * a system call makes another system call.
1432 */
1433 fprintf(stderr, "syscall: missing exit\n");
1434 }
1435 tcp->flags &= ~TCB_INSYSCALL;
1436 }
1437 }
1438#endif /* SUNOS4 */
1439#ifdef LINUX
1440#if defined (I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001441 if (upeek(tcp, 4*EAX, &eax) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001442 return -1;
1443 if (eax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1444 if (debug)
1445 fprintf(stderr, "stray syscall exit: eax = %ld\n", eax);
1446 return 0;
1447 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001448#elif defined (X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001449 if (upeek(tcp, 8*RAX, &rax) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00001450 return -1;
Roland McGrath998fac72004-06-23 01:40:45 +00001451 if (current_personality == 1)
1452 rax = (long int)(int)rax; /* sign extend from 32 bits */
Michal Ludvig0e035502002-09-23 15:41:01 +00001453 if (rax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1454 if (debug)
1455 fprintf(stderr, "stray syscall exit: rax = %ld\n", rax);
1456 return 0;
1457 }
Michal Ludvig10a88d02002-10-07 14:31:00 +00001458#elif defined (S390) || defined (S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001459 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001460 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001461 if (syscall_mode != -ENOSYS)
1462 syscall_mode = tcp->scno;
1463 if (gpr2 != syscall_mode && !(tcp->flags & TCB_INSYSCALL)) {
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001464 if (debug)
1465 fprintf(stderr, "stray syscall exit: gpr2 = %ld\n", gpr2);
1466 return 0;
1467 }
Roland McGrath96dc5142003-01-20 10:23:04 +00001468 else if (((tcp->flags & (TCB_INSYSCALL|TCB_WAITEXECVE))
1469 == (TCB_INSYSCALL|TCB_WAITEXECVE))
1470 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1471 /*
1472 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1473 * flag set for the post-execve SIGTRAP to see and reset.
1474 */
1475 gpr2 = 0;
1476 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001477#elif defined (POWERPC)
1478# define SO_MASK 0x10000000
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001479 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001480 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001481 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &result) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001482 return -1;
1483 if (flags & SO_MASK)
1484 result = -result;
1485#elif defined (M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001486 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001487 return -1;
1488 if (d0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1489 if (debug)
1490 fprintf(stderr, "stray syscall exit: d0 = %ld\n", d0);
1491 return 0;
1492 }
1493#elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001494 /*
1495 * Nothing required
1496 */
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001497#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001498 if (upeek(tcp, PT_R0, &r0) < 0)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001499 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001500#elif defined (HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001501 if (upeek(tcp, PT_GR28, &r28) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001502 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001503#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001504 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001505 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001506 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001507 return -1;
1508 if (ia32 && r8 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1509 if (debug)
1510 fprintf(stderr, "stray syscall exit: r8 = %ld\n", r8);
1511 return 0;
1512 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001513#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001514 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001515 return -1;
1516 if (r10 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1517 if (debug)
1518 fprintf(stderr, "stray syscall exit: r10 = %ld\n", r10);
1519 return 0;
1520 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001521#elif defined(MICROBLAZE)
1522 if (upeek(tcp, 3 * 4, &r3) < 0)
1523 return -1;
1524 if (r3 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1525 if (debug)
1526 fprintf(stderr, "stray syscall exit: r3 = %ld\n", r3);
1527 return 0;
1528 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001529#endif
1530#endif /* LINUX */
Pavel Machek4dc3b142000-02-01 17:58:41 +00001531 return 1;
1532}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001533
Roland McGrathc1e45922008-05-27 23:18:29 +00001534#ifdef LINUX
1535/*
1536 * Check the syscall return value register value for whether it is
1537 * a negated errno code indicating an error, or a success return value.
1538 */
1539static inline int
1540is_negated_errno(unsigned long int val)
1541{
1542 unsigned long int max = -(long int) nerrnos;
1543 if (personality_wordsize[current_personality] < sizeof(val)) {
1544 val = (unsigned int) val;
1545 max = (unsigned int) max;
1546 }
1547 return val > max;
1548}
1549#endif
1550
Roland McGratha4d48532005-06-08 20:45:28 +00001551static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001552get_error(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001553{
1554 int u_error = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001555#ifdef LINUX
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001556# if defined(S390) || defined(S390X)
Roland McGrathc1e45922008-05-27 23:18:29 +00001557 if (is_negated_errno(gpr2)) {
1558 tcp->u_rval = -1;
1559 u_error = -gpr2;
1560 }
1561 else {
1562 tcp->u_rval = gpr2;
1563 u_error = 0;
1564 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001565# elif defined(I386)
Roland McGrathc1e45922008-05-27 23:18:29 +00001566 if (is_negated_errno(eax)) {
1567 tcp->u_rval = -1;
1568 u_error = -eax;
1569 }
1570 else {
1571 tcp->u_rval = eax;
1572 u_error = 0;
1573 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001574# elif defined(X86_64)
Roland McGrathc1e45922008-05-27 23:18:29 +00001575 if (is_negated_errno(rax)) {
1576 tcp->u_rval = -1;
1577 u_error = -rax;
1578 }
1579 else {
1580 tcp->u_rval = rax;
1581 u_error = 0;
1582 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001583# elif defined(IA64)
Roland McGrathc1e45922008-05-27 23:18:29 +00001584 if (ia32) {
1585 int err;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001586
Roland McGrathc1e45922008-05-27 23:18:29 +00001587 err = (int)r8;
1588 if (is_negated_errno(err)) {
1589 tcp->u_rval = -1;
1590 u_error = -err;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001591 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001592 else {
1593 tcp->u_rval = err;
1594 u_error = 0;
1595 }
1596 } else {
1597 if (r10) {
1598 tcp->u_rval = -1;
1599 u_error = r8;
1600 } else {
1601 tcp->u_rval = r8;
1602 u_error = 0;
1603 }
1604 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001605# elif defined(MIPS)
Wichert Akkermanf90da011999-10-31 21:15:38 +00001606 if (a3) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001607 tcp->u_rval = -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001608 u_error = r2;
1609 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001610 tcp->u_rval = r2;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001611 u_error = 0;
1612 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001613# elif defined(POWERPC)
Roland McGrathc1e45922008-05-27 23:18:29 +00001614 if (is_negated_errno(result)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001615 tcp->u_rval = -1;
1616 u_error = -result;
1617 }
1618 else {
1619 tcp->u_rval = result;
1620 u_error = 0;
1621 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001622# elif defined(M68K)
Roland McGrathc1e45922008-05-27 23:18:29 +00001623 if (is_negated_errno(d0)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001624 tcp->u_rval = -1;
1625 u_error = -d0;
1626 }
1627 else {
1628 tcp->u_rval = d0;
1629 u_error = 0;
1630 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001631# elif defined(ARM)
Roland McGrathc1e45922008-05-27 23:18:29 +00001632 if (is_negated_errno(regs.ARM_r0)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001633 tcp->u_rval = -1;
Roland McGrath0f87c492003-06-03 23:29:04 +00001634 u_error = -regs.ARM_r0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001635 }
1636 else {
Roland McGrath0f87c492003-06-03 23:29:04 +00001637 tcp->u_rval = regs.ARM_r0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001638 u_error = 0;
1639 }
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001640# elif defined(AVR32)
1641 if (regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1642 tcp->u_rval = -1;
1643 u_error = -regs.r12;
1644 }
1645 else {
1646 tcp->u_rval = regs.r12;
1647 u_error = 0;
1648 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001649# elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001650 if (is_negated_errno(r0)) {
1651 tcp->u_rval = -1;
1652 u_error = -r0;
1653 } else {
1654 tcp->u_rval = r0;
1655 u_error = 0;
1656 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001657# elif defined(ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001658 if (a3) {
1659 tcp->u_rval = -1;
1660 u_error = r0;
1661 }
1662 else {
1663 tcp->u_rval = r0;
1664 u_error = 0;
1665 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001666# elif defined(SPARC)
Mike Frysinger8566c502009-10-12 11:05:14 -04001667 if (regs.psr & PSR_C) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001668 tcp->u_rval = -1;
Mike Frysinger8566c502009-10-12 11:05:14 -04001669 u_error = regs.u_regs[U_REG_O0];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001670 }
1671 else {
Mike Frysinger8566c502009-10-12 11:05:14 -04001672 tcp->u_rval = regs.u_regs[U_REG_O0];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001673 u_error = 0;
1674 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001675# elif defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001676 if (regs.tstate & 0x1100000000UL) {
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001677 tcp->u_rval = -1;
Mike Frysinger8566c502009-10-12 11:05:14 -04001678 u_error = regs.u_regs[U_REG_O0];
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001679 }
1680 else {
Mike Frysinger8566c502009-10-12 11:05:14 -04001681 tcp->u_rval = regs.u_regs[U_REG_O0];
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001682 u_error = 0;
1683 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001684# elif defined(HPPA)
Roland McGrathc1e45922008-05-27 23:18:29 +00001685 if (is_negated_errno(r28)) {
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001686 tcp->u_rval = -1;
1687 u_error = -r28;
1688 }
1689 else {
1690 tcp->u_rval = r28;
1691 u_error = 0;
1692 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001693# elif defined(SH)
Roland McGrathc1e45922008-05-27 23:18:29 +00001694 /* interpret R0 as return value or error number */
1695 if (is_negated_errno(r0)) {
1696 tcp->u_rval = -1;
1697 u_error = -r0;
1698 }
1699 else {
1700 tcp->u_rval = r0;
1701 u_error = 0;
1702 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001703# elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001704 /* interpret result as return value or error number */
1705 if (is_negated_errno(r9)) {
1706 tcp->u_rval = -1;
1707 u_error = -r9;
1708 }
1709 else {
1710 tcp->u_rval = r9;
1711 u_error = 0;
1712 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001713# elif defined(CRISV10) || defined(CRISV32)
1714 if (r10 && (unsigned) -r10 < nerrnos) {
1715 tcp->u_rval = -1;
1716 u_error = -r10;
1717 }
1718 else {
1719 tcp->u_rval = r10;
1720 u_error = 0;
1721 }
Chris Metcalfc8c66982009-12-28 10:00:15 -05001722# elif defined(TILE)
1723 long rval;
1724 /* interpret result as return value or error number */
1725 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1726 return -1;
1727 if (rval < 0 && rval > -nerrnos) {
1728 tcp->u_rval = -1;
1729 u_error = -rval;
1730 }
1731 else {
1732 tcp->u_rval = rval;
1733 u_error = 0;
1734 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001735# elif defined(MICROBLAZE)
1736 /* interpret result as return value or error number */
1737 if (is_negated_errno(r3)) {
1738 tcp->u_rval = -1;
1739 u_error = -r3;
1740 }
1741 else {
1742 tcp->u_rval = r3;
1743 u_error = 0;
1744 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001745# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001746#endif /* LINUX */
1747#ifdef SUNOS4
1748 /* get error code from user struct */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001749 if (upeek(tcp, uoff(u_error), &u_error) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001750 return -1;
1751 u_error >>= 24; /* u_error is a char */
1752
1753 /* get system call return value */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001754 if (upeek(tcp, uoff(u_rval1), &tcp->u_rval) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001755 return -1;
1756#endif /* SUNOS4 */
1757#ifdef SVR4
1758#ifdef SPARC
1759 /* Judicious guessing goes a long way. */
1760 if (tcp->status.pr_reg[R_PSR] & 0x100000) {
1761 tcp->u_rval = -1;
1762 u_error = tcp->status.pr_reg[R_O0];
1763 }
1764 else {
1765 tcp->u_rval = tcp->status.pr_reg[R_O0];
1766 u_error = 0;
1767 }
1768#endif /* SPARC */
1769#ifdef I386
1770 /* Wanna know how to kill an hour single-stepping? */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001771 if (tcp->status.PR_REG[EFL] & 0x1) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001772 tcp->u_rval = -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001773 u_error = tcp->status.PR_REG[EAX];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001774 }
1775 else {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001776 tcp->u_rval = tcp->status.PR_REG[EAX];
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001777#ifdef HAVE_LONG_LONG
1778 tcp->u_lrval =
1779 ((unsigned long long) tcp->status.PR_REG[EDX] << 32) +
1780 tcp->status.PR_REG[EAX];
1781#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001782 u_error = 0;
1783 }
1784#endif /* I386 */
Michal Ludvig0e035502002-09-23 15:41:01 +00001785#ifdef X86_64
1786 /* Wanna know how to kill an hour single-stepping? */
1787 if (tcp->status.PR_REG[EFLAGS] & 0x1) {
1788 tcp->u_rval = -1;
1789 u_error = tcp->status.PR_REG[RAX];
1790 }
1791 else {
1792 tcp->u_rval = tcp->status.PR_REG[RAX];
1793 u_error = 0;
1794 }
1795#endif /* X86_64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001796#ifdef MIPS
1797 if (tcp->status.pr_reg[CTX_A3]) {
1798 tcp->u_rval = -1;
1799 u_error = tcp->status.pr_reg[CTX_V0];
1800 }
1801 else {
1802 tcp->u_rval = tcp->status.pr_reg[CTX_V0];
1803 u_error = 0;
1804 }
1805#endif /* MIPS */
1806#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001807#ifdef FREEBSD
1808 if (regs.r_eflags & PSL_C) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001809 tcp->u_rval = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001810 u_error = regs.r_eax;
1811 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001812 tcp->u_rval = regs.r_eax;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001813 tcp->u_lrval =
1814 ((unsigned long long) regs.r_edx << 32) + regs.r_eax;
1815 u_error = 0;
1816 }
Roland McGrath761b5d72002-12-15 23:58:31 +00001817#endif /* FREEBSD */
Pavel Machek4dc3b142000-02-01 17:58:41 +00001818 tcp->u_error = u_error;
1819 return 1;
1820}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001821
Roland McGrathb69f81b2002-12-21 23:25:18 +00001822int
1823force_result(tcp, error, rval)
1824 struct tcb *tcp;
1825 int error;
1826 long rval;
1827{
1828#ifdef LINUX
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001829# if defined(S390) || defined(S390X)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001830 gpr2 = error ? -error : rval;
Roland McGrathb69f81b2002-12-21 23:25:18 +00001831 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_GPR2, gpr2) < 0)
1832 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001833# elif defined(I386)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001834 eax = error ? -error : rval;
1835 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(EAX * 4), eax) < 0)
1836 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001837# elif defined(X86_64)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001838 rax = error ? -error : rval;
Roland McGrath998fac72004-06-23 01:40:45 +00001839 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(RAX * 8), rax) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001840 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001841# elif defined(IA64)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001842 if (ia32) {
1843 r8 = error ? -error : rval;
1844 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0)
1845 return -1;
1846 }
1847 else {
1848 if (error) {
1849 r8 = error;
1850 r10 = -1;
1851 }
1852 else {
1853 r8 = rval;
1854 r10 = 0;
1855 }
1856 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0 ||
1857 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R10), r10) < 0)
1858 return -1;
1859 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001860# elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001861 r0 = error ? -error : rval;
1862 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_R0, r0) < 0)
1863 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001864# elif defined(MIPS)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001865 if (error) {
1866 r2 = error;
1867 a3 = -1;
1868 }
1869 else {
1870 r2 = rval;
1871 a3 = 0;
1872 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001873 /* PTRACE_POKEUSER is OK even for n32 since rval is only a long. */
Roland McGrathb69f81b2002-12-21 23:25:18 +00001874 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1875 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), r2) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001876 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001877# elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001878 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001879 return -1;
1880 if (error) {
1881 flags |= SO_MASK;
1882 result = error;
1883 }
1884 else {
1885 flags &= ~SO_MASK;
1886 result = rval;
1887 }
Roland McGratheb285352003-01-14 09:59:00 +00001888 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_CCR), flags) < 0 ||
1889 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_R3), result) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001890 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001891# elif defined(M68K)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001892 d0 = error ? -error : rval;
1893 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_D0), d0) < 0)
1894 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001895# elif defined(ARM)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001896 regs.ARM_r0 = error ? -error : rval;
1897 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*0), regs.ARM_r0) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001898 return -1;
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001899# elif defined(AVR32)
1900 regs.r12 = error ? -error : rval;
1901 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_R12, regs.r12) < 0)
1902 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001903# elif defined(ALPHA)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001904 if (error) {
1905 a3 = -1;
1906 r0 = error;
1907 }
1908 else {
1909 a3 = 0;
1910 r0 = rval;
1911 }
1912 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1913 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R0), r0) < 0)
1914 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001915# elif defined(SPARC)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001916 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1917 return -1;
1918 if (error) {
Mike Frysinger8566c502009-10-12 11:05:14 -04001919 regs.psr |= PSR_C;
1920 regs.u_regs[U_REG_O0] = error;
Roland McGrathb69f81b2002-12-21 23:25:18 +00001921 }
1922 else {
Mike Frysinger8566c502009-10-12 11:05:14 -04001923 regs.psr &= ~PSR_C;
1924 regs.u_regs[U_REG_O0] = rval;
Roland McGrathb69f81b2002-12-21 23:25:18 +00001925 }
1926 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1927 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001928# elif defined(SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001929 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1930 return -1;
1931 if (error) {
Mike Frysinger8566c502009-10-12 11:05:14 -04001932 regs.tstate |= 0x1100000000UL;
1933 regs.u_regs[U_REG_O0] = error;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001934 }
1935 else {
Mike Frysinger8566c502009-10-12 11:05:14 -04001936 regs.tstate &= ~0x1100000000UL;
1937 regs.u_regs[U_REG_O0] = rval;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001938 }
1939 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1940 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001941# elif defined(HPPA)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001942 r28 = error ? -error : rval;
1943 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR28), r28) < 0)
1944 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001945# elif defined(SH)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001946 r0 = error ? -error : rval;
1947 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*REG_REG0), r0) < 0)
1948 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001949# elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001950 r9 = error ? -error : rval;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001951 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_GENERAL(9), r9) < 0)
1952 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001953# endif
Roland McGrathb69f81b2002-12-21 23:25:18 +00001954#endif /* LINUX */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001955
Roland McGrathb69f81b2002-12-21 23:25:18 +00001956#ifdef SUNOS4
Roland McGratheb9e2e82009-06-02 16:49:22 -07001957 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_error),
1958 error << 24) < 0 ||
1959 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_rval1), rval) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001960 return -1;
1961#endif /* SUNOS4 */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001962
Roland McGrathb69f81b2002-12-21 23:25:18 +00001963#ifdef SVR4
1964 /* XXX no clue */
1965 return -1;
1966#endif /* SVR4 */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001967
Roland McGrathb69f81b2002-12-21 23:25:18 +00001968#ifdef FREEBSD
1969 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001970 perror("pread");
1971 return -1;
1972 }
Roland McGrathb69f81b2002-12-21 23:25:18 +00001973 if (error) {
1974 regs.r_eflags |= PSL_C;
1975 regs.r_eax = error;
1976 }
1977 else {
1978 regs.r_eflags &= ~PSL_C;
1979 regs.r_eax = rval;
1980 }
1981 if (pwrite(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001982 perror("pwrite");
1983 return -1;
1984 }
Roland McGrathb69f81b2002-12-21 23:25:18 +00001985#endif /* FREEBSD */
1986
1987 /* All branches reach here on success (only). */
1988 tcp->u_error = error;
1989 tcp->u_rval = rval;
1990 return 0;
1991}
1992
Roland McGratha4d48532005-06-08 20:45:28 +00001993static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001994syscall_enter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001995{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001996#ifdef LINUX
Michal Ludvig10a88d02002-10-07 14:31:00 +00001997#if defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001998 {
1999 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002000 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2001 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002002 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002003 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00002004 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002005 if (upeek(tcp,i==0 ? PT_ORIGGPR2:PT_GPR2+i*sizeof(long), &tcp->u_arg[i]) < 0)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00002006 return -1;
2007 }
2008 }
2009#elif defined (ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002010 {
2011 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002012 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2013 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002014 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002015 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002016 for (i = 0; i < tcp->u_nargs; i++) {
Wichert Akkermanb859bea1999-04-18 22:50:50 +00002017 /* WTA: if scno is out-of-bounds this will bomb. Add range-check
2018 * for scno somewhere above here!
2019 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002020 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002021 return -1;
2022 }
2023 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002024#elif defined (IA64)
2025 {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002026 if (!ia32) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00002027 unsigned long *out0, cfm, sof, sol, i;
2028 long rbs_end;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002029 /* be backwards compatible with kernel < 2.4.4... */
2030# ifndef PT_RBS_END
2031# define PT_RBS_END PT_AR_BSP
2032# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002033
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002034 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002035 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002036 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002037 return -1;
2038
2039 sof = (cfm >> 0) & 0x7f;
2040 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002041 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002042
2043 if (tcp->scno >= 0 && tcp->scno < nsyscalls
2044 && sysent[tcp->scno].nargs != -1)
2045 tcp->u_nargs = sysent[tcp->scno].nargs;
2046 else
2047 tcp->u_nargs = MAX_ARGS;
2048 for (i = 0; i < tcp->u_nargs; ++i) {
2049 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
2050 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
2051 return -1;
2052 }
2053 } else {
2054 int i;
2055
2056 if (/* EBX = out0 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002057 upeek(tcp, PT_R11, (long *) &tcp->u_arg[0]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002058 /* ECX = out1 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002059 || upeek(tcp, PT_R9, (long *) &tcp->u_arg[1]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002060 /* EDX = out2 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002061 || upeek(tcp, PT_R10, (long *) &tcp->u_arg[2]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002062 /* ESI = out3 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002063 || upeek(tcp, PT_R14, (long *) &tcp->u_arg[3]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002064 /* EDI = out4 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002065 || upeek(tcp, PT_R15, (long *) &tcp->u_arg[4]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002066 /* EBP = out5 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002067 || upeek(tcp, PT_R13, (long *) &tcp->u_arg[5]) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002068 return -1;
2069
2070 for (i = 0; i < 6; ++i)
2071 /* truncate away IVE sign-extension */
2072 tcp->u_arg[i] &= 0xffffffff;
2073
2074 if (tcp->scno >= 0 && tcp->scno < nsyscalls
2075 && sysent[tcp->scno].nargs != -1)
2076 tcp->u_nargs = sysent[tcp->scno].nargs;
2077 else
2078 tcp->u_nargs = 5;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002079 }
2080 }
Roland McGrath542c2c62008-05-20 01:11:56 +00002081#elif defined (LINUX_MIPSN32) || defined (LINUX_MIPSN64)
2082 /* N32 and N64 both use up to six registers. */
2083 {
2084 unsigned long long regs[38];
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002085 int i, nargs;
Roland McGrath542c2c62008-05-20 01:11:56 +00002086
2087 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2088 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrathc1e45922008-05-27 23:18:29 +00002089 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002090 nargs = tcp->u_nargs = MAX_ARGS;
Roland McGrath542c2c62008-05-20 01:11:56 +00002091
David Daney20037042010-02-09 21:22:30 +00002092 if (ptrace (PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00002093 return -1;
2094
Roland McGratheb9e2e82009-06-02 16:49:22 -07002095 for(i = 0; i < nargs; i++) {
Roland McGrath542c2c62008-05-20 01:11:56 +00002096 tcp->u_arg[i] = regs[REG_A0 + i];
2097# if defined (LINUX_MIPSN32)
2098 tcp->ext_arg[i] = regs[REG_A0 + i];
2099# endif
2100 }
2101 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00002102#elif defined (MIPS)
2103 {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002104 long sp;
2105 int i, nargs;
Wichert Akkermanf90da011999-10-31 21:15:38 +00002106
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002107 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2108 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002109 else
Dmitry V. Levin414fe7d2009-07-08 11:21:17 +00002110 nargs = tcp->u_nargs = MAX_ARGS;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002111 if(nargs > 4) {
Dmitry V. Levin414fe7d2009-07-08 11:21:17 +00002112 if(upeek(tcp, REG_SP, &sp) < 0)
2113 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002114 for(i = 0; i < 4; i++) {
Dmitry V. Levin414fe7d2009-07-08 11:21:17 +00002115 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i])<0)
2116 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00002117 }
2118 umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]),
2119 (char *)(tcp->u_arg + 4));
2120 } else {
Dmitry V. Levin414fe7d2009-07-08 11:21:17 +00002121 for(i = 0; i < nargs; i++) {
2122 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
2123 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00002124 }
2125 }
2126 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002127#elif defined (POWERPC)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002128# ifndef PT_ORIG_R3
2129# define PT_ORIG_R3 34
2130# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002131 {
2132 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002133 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2134 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002135 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002136 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002137 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002138 if (upeek(tcp, (i==0) ?
Roland McGratheb285352003-01-14 09:59:00 +00002139 (sizeof(unsigned long)*PT_ORIG_R3) :
2140 ((i+PT_R3)*sizeof(unsigned long)),
2141 &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002142 return -1;
2143 }
2144 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002145#elif defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002146 {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002147 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002148
2149 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2150 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002151 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002152 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002153 for (i = 0; i < tcp->u_nargs; i++)
Mike Frysinger8566c502009-10-12 11:05:14 -04002154 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002155 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002156#elif defined (HPPA)
2157 {
2158 int i;
2159
2160 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2161 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002162 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002163 tcp->u_nargs = MAX_ARGS;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002164 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002165 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002166 return -1;
2167 }
2168 }
Roland McGrath0f87c492003-06-03 23:29:04 +00002169#elif defined(ARM)
2170 {
2171 int i;
2172
2173 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2174 tcp->u_nargs = sysent[tcp->scno].nargs;
2175 else
2176 tcp->u_nargs = MAX_ARGS;
2177 for (i = 0; i < tcp->u_nargs; i++)
2178 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002179 }
2180#elif defined(AVR32)
2181 tcp->u_nargs = sysent[tcp->scno].nargs;
2182 tcp->u_arg[0] = regs.r12;
2183 tcp->u_arg[1] = regs.r11;
2184 tcp->u_arg[2] = regs.r10;
2185 tcp->u_arg[3] = regs.r9;
2186 tcp->u_arg[4] = regs.r5;
2187 tcp->u_arg[5] = regs.r3;
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00002188#elif defined(BFIN)
2189 {
2190 int i;
2191 int argreg[] = {PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5};
2192
2193 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2194 tcp->u_nargs = sysent[tcp->scno].nargs;
2195 else
2196 tcp->u_nargs = sizeof(argreg) / sizeof(argreg[0]);
2197
2198 for (i = 0; i < tcp->u_nargs; ++i)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002199 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00002200 return -1;
2201 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00002202#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002203 {
2204 int i;
2205 static int syscall_regs[] = {
2206 REG_REG0+4, REG_REG0+5, REG_REG0+6, REG_REG0+7,
2207 REG_REG0, REG_REG0+1, REG_REG0+2
2208 };
Wichert Akkermanccef6372002-05-01 16:39:22 +00002209
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002210 tcp->u_nargs = sysent[tcp->scno].nargs;
2211 for (i = 0; i < tcp->u_nargs; i++) {
2212 if (upeek(tcp, 4*syscall_regs[i], &tcp->u_arg[i]) < 0)
2213 return -1;
2214 }
2215 }
Roland McGrathf5a47772003-06-26 22:40:42 +00002216#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00002217 {
2218 int i;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002219 /* Registers used by SH5 Linux system calls for parameters */
Roland McGrathe1e584b2003-06-02 19:18:58 +00002220 static int syscall_regs[] = { 2, 3, 4, 5, 6, 7 };
2221
2222 /*
2223 * TODO: should also check that the number of arguments encoded
2224 * in the trap number matches the number strace expects.
2225 */
2226 /*
Dmitry V. Levin414fe7d2009-07-08 11:21:17 +00002227 assert(sysent[tcp->scno].nargs <
2228 sizeof(syscall_regs)/sizeof(syscall_regs[0]));
Roland McGrathe1e584b2003-06-02 19:18:58 +00002229 */
2230
2231 tcp->u_nargs = sysent[tcp->scno].nargs;
2232 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002233 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00002234 return -1;
2235 }
2236 }
2237
Michal Ludvig0e035502002-09-23 15:41:01 +00002238#elif defined(X86_64)
2239 {
2240 int i;
2241 static int argreg[SUPPORTED_PERSONALITIES][MAX_ARGS] = {
2242 {RDI,RSI,RDX,R10,R8,R9}, /* x86-64 ABI */
Roland McGrath5a9c6ad2005-02-02 03:06:52 +00002243 {RBX,RCX,RDX,RSI,RDI,RBP} /* i386 ABI */
Michal Ludvig0e035502002-09-23 15:41:01 +00002244 };
Roland McGrath761b5d72002-12-15 23:58:31 +00002245
Michal Ludvig0e035502002-09-23 15:41:01 +00002246 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2247 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002248 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002249 tcp->u_nargs = MAX_ARGS;
Michal Ludvig0e035502002-09-23 15:41:01 +00002250 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002251 if (upeek(tcp, argreg[current_personality][i]*8, &tcp->u_arg[i]) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00002252 return -1;
2253 }
2254 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02002255#elif defined(MICROBLAZE)
2256 {
2257 int i;
2258 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
2259 tcp->u_nargs = sysent[tcp->scno].nargs;
2260 else
2261 tcp->u_nargs = 0;
2262 for (i = 0; i < tcp->u_nargs; i++) {
2263 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
2264 return -1;
2265 }
2266 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002267#elif defined(CRISV10) || defined(CRISV32)
2268 {
2269 int i;
2270 static const int crisregs[] = {
2271 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
2272 4*PT_R13, 4*PT_MOF, 4*PT_SRP
2273 };
2274
2275 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
2276 tcp->u_nargs = sysent[tcp->scno].nargs;
2277 else
2278 tcp->u_nargs = 0;
2279 for (i = 0; i < tcp->u_nargs; i++) {
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00002280 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002281 return -1;
2282 }
2283 }
Chris Metcalfc8c66982009-12-28 10:00:15 -05002284#elif defined(TILE)
2285 {
2286 int i;
2287 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2288 tcp->u_nargs = sysent[tcp->scno].nargs;
2289 else
2290 tcp->u_nargs = MAX_ARGS;
2291 for (i = 0; i < tcp->u_nargs; ++i) {
2292 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
2293 return -1;
2294 }
2295 }
Andreas Schwab246888d2010-06-05 21:50:30 +02002296#elif defined (M68K)
2297 {
2298 int i;
2299 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2300 tcp->u_nargs = sysent[tcp->scno].nargs;
2301 else
2302 tcp->u_nargs = MAX_ARGS;
2303 for (i = 0; i < tcp->u_nargs; i++) {
2304 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
2305 return -1;
2306 }
2307 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00002308#else /* Other architecture (like i386) (32bits specific) */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002309 {
2310 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002311 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2312 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002313 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002314 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002315 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002316 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002317 return -1;
2318 }
2319 }
Roland McGrath761b5d72002-12-15 23:58:31 +00002320#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002321#endif /* LINUX */
2322#ifdef SUNOS4
2323 {
2324 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002325 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2326 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002327 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002328 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002329 for (i = 0; i < tcp->u_nargs; i++) {
2330 struct user *u;
2331
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002332 if (upeek(tcp, uoff(u_arg[0]) +
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002333 (i*sizeof(u->u_arg[0])), &tcp->u_arg[i]) < 0)
2334 return -1;
2335 }
2336 }
2337#endif /* SUNOS4 */
2338#ifdef SVR4
2339#ifdef MIPS
2340 /*
2341 * SGI is broken: even though it has pr_sysarg, it doesn't
2342 * set them on system call entry. Get a clue.
2343 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002344 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002345 tcp->u_nargs = sysent[tcp->scno].nargs;
2346 else
2347 tcp->u_nargs = tcp->status.pr_nsysarg;
2348 if (tcp->u_nargs > 4) {
2349 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2350 4*sizeof(tcp->u_arg[0]));
2351 umoven(tcp, tcp->status.pr_reg[CTX_SP] + 16,
2352 (tcp->u_nargs - 4)*sizeof(tcp->u_arg[0]), (char *) (tcp->u_arg + 4));
2353 }
2354 else {
2355 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2356 tcp->u_nargs*sizeof(tcp->u_arg[0]));
2357 }
John Hughes25299712001-03-06 10:10:06 +00002358#elif UNIXWARE >= 2
2359 /*
2360 * Like SGI, UnixWare doesn't set pr_sysarg until system call exit
2361 */
2362 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2363 tcp->u_nargs = sysent[tcp->scno].nargs;
2364 else
2365 tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;
2366 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
2367 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2368#elif defined (HAVE_PR_SYSCALL)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002369 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002370 tcp->u_nargs = sysent[tcp->scno].nargs;
2371 else
2372 tcp->u_nargs = tcp->status.pr_nsysarg;
2373 {
2374 int i;
2375 for (i = 0; i < tcp->u_nargs; i++)
2376 tcp->u_arg[i] = tcp->status.pr_sysarg[i];
2377 }
John Hughes25299712001-03-06 10:10:06 +00002378#elif defined (I386)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002379 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002380 tcp->u_nargs = sysent[tcp->scno].nargs;
2381 else
2382 tcp->u_nargs = 5;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002383 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002384 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
John Hughes25299712001-03-06 10:10:06 +00002385#else
2386 I DONT KNOW WHAT TO DO
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002387#endif /* !HAVE_PR_SYSCALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002388#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002389#ifdef FREEBSD
2390 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2391 sysent[tcp->scno].nargs > tcp->status.val)
2392 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002393 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002394 tcp->u_nargs = tcp->status.val;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002395 if (tcp->u_nargs < 0)
2396 tcp->u_nargs = 0;
2397 if (tcp->u_nargs > MAX_ARGS)
2398 tcp->u_nargs = MAX_ARGS;
2399 switch(regs.r_eax) {
2400 case SYS___syscall:
2401 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2402 regs.r_esp + sizeof(int) + sizeof(quad_t));
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002403 break;
2404 case SYS_syscall:
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002405 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2406 regs.r_esp + 2 * sizeof(int));
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002407 break;
2408 default:
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002409 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2410 regs.r_esp + sizeof(int));
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002411 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002412 }
2413#endif /* FREEBSD */
Pavel Machek4dc3b142000-02-01 17:58:41 +00002414 return 1;
2415}
2416
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002417static int
2418trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002419{
2420 int sys_res;
2421 struct timeval tv;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002422 int res, scno_good;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002423 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002424
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002425 /* Measure the exit time as early as possible to avoid errors. */
2426 if (dtime || cflag)
2427 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002428
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002429 /* BTW, why we don't just memorize syscall no. on entry
2430 * in tcp->something?
2431 */
2432 scno_good = res = get_scno(tcp);
2433 if (res == 0)
2434 return res;
2435 if (res == 1)
2436 res = syscall_fixup(tcp);
2437 if (res == 0)
2438 return res;
2439 if (res == 1)
2440 res = get_error(tcp);
2441 if (res == 0)
2442 return res;
2443 if (res == 1)
2444 internal_syscall(tcp);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002445
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002446 if (res == 1 && tcp->scno >= 0 && tcp->scno < nsyscalls &&
2447 !(qual_flags[tcp->scno] & QUAL_TRACE)) {
Pavel Machek4dc3b142000-02-01 17:58:41 +00002448 tcp->flags &= ~TCB_INSYSCALL;
2449 return 0;
2450 }
2451
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002452 if (tcp->flags & TCB_REPRINT) {
2453 printleader(tcp);
2454 tprintf("<... ");
2455 if (scno_good != 1)
2456 tprintf("????");
2457 else if (tcp->scno >= nsyscalls || tcp->scno < 0)
2458 tprintf("syscall_%lu", tcp->scno);
2459 else
2460 tprintf("%s", sysent[tcp->scno].sys_name);
2461 tprintf(" resumed> ");
2462 }
2463
2464 if (cflag) {
2465 struct timeval t = tv;
2466 int rc = count_syscall(tcp, &t);
2467 if (cflag == CFLAG_ONLY_STATS)
2468 {
2469 tcp->flags &= ~TCB_INSYSCALL;
2470 return rc;
2471 }
2472 }
2473
2474 if (res != 1) {
2475 tprintf(") ");
2476 tabto(acolumn);
2477 tprintf("= ? <unavailable>");
2478 printtrailer();
2479 tcp->flags &= ~TCB_INSYSCALL;
2480 return res;
2481 }
2482
2483 if (tcp->scno >= nsyscalls || tcp->scno < 0
2484 || (qual_flags[tcp->scno] & QUAL_RAW))
2485 sys_res = printargs(tcp);
2486 else {
2487 if (not_failing_only && tcp->u_error)
2488 return 0; /* ignore failed syscalls */
2489 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2490 }
2491
2492 u_error = tcp->u_error;
2493 tprintf(") ");
2494 tabto(acolumn);
2495 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2496 qual_flags[tcp->scno] & QUAL_RAW) {
2497 if (u_error)
2498 tprintf("= -1 (errno %ld)", u_error);
2499 else
2500 tprintf("= %#lx", tcp->u_rval);
2501 }
2502 else if (!(sys_res & RVAL_NONE) && u_error) {
2503 switch (u_error) {
2504#ifdef LINUX
2505 case ERESTARTSYS:
2506 tprintf("= ? ERESTARTSYS (To be restarted)");
2507 break;
2508 case ERESTARTNOINTR:
2509 tprintf("= ? ERESTARTNOINTR (To be restarted)");
2510 break;
2511 case ERESTARTNOHAND:
2512 tprintf("= ? ERESTARTNOHAND (To be restarted)");
2513 break;
2514 case ERESTART_RESTARTBLOCK:
2515 tprintf("= ? ERESTART_RESTARTBLOCK (To be restarted)");
2516 break;
2517#endif /* LINUX */
2518 default:
2519 tprintf("= -1 ");
2520 if (u_error < 0)
2521 tprintf("E??? (errno %ld)", u_error);
2522 else if (u_error < nerrnos)
2523 tprintf("%s (%s)", errnoent[u_error],
2524 strerror(u_error));
2525 else
2526 tprintf("ERRNO_%ld (%s)", u_error,
2527 strerror(u_error));
2528 break;
2529 }
2530 if ((sys_res & RVAL_STR) && tcp->auxstr)
2531 tprintf(" (%s)", tcp->auxstr);
2532 }
2533 else {
2534 if (sys_res & RVAL_NONE)
2535 tprintf("= ?");
2536 else {
2537 switch (sys_res & RVAL_MASK) {
2538 case RVAL_HEX:
2539 tprintf("= %#lx", tcp->u_rval);
2540 break;
2541 case RVAL_OCTAL:
2542 tprintf("= %#lo", tcp->u_rval);
2543 break;
2544 case RVAL_UDECIMAL:
2545 tprintf("= %lu", tcp->u_rval);
2546 break;
2547 case RVAL_DECIMAL:
2548 tprintf("= %ld", tcp->u_rval);
2549 break;
2550#ifdef HAVE_LONG_LONG
2551 case RVAL_LHEX:
2552 tprintf("= %#llx", tcp->u_lrval);
2553 break;
2554 case RVAL_LOCTAL:
2555 tprintf("= %#llo", tcp->u_lrval);
2556 break;
2557 case RVAL_LUDECIMAL:
2558 tprintf("= %llu", tcp->u_lrval);
2559 break;
2560 case RVAL_LDECIMAL:
2561 tprintf("= %lld", tcp->u_lrval);
2562 break;
2563#endif
2564 default:
2565 fprintf(stderr,
2566 "invalid rval format\n");
2567 break;
2568 }
2569 }
2570 if ((sys_res & RVAL_STR) && tcp->auxstr)
2571 tprintf(" (%s)", tcp->auxstr);
2572 }
2573 if (dtime) {
2574 tv_sub(&tv, &tv, &tcp->etime);
2575 tprintf(" <%ld.%06ld>",
2576 (long) tv.tv_sec, (long) tv.tv_usec);
2577 }
2578 printtrailer();
2579
2580 dumpio(tcp);
2581 if (fflush(tcp->outf) == EOF)
2582 return -1;
2583 tcp->flags &= ~TCB_INSYSCALL;
2584 return 0;
2585}
2586
2587static int
2588trace_syscall_entering(struct tcb *tcp)
2589{
2590 int sys_res;
2591 int res, scno_good;
2592
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002593 scno_good = res = get_scno(tcp);
2594 if (res == 0)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002595 return res;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002596 if (res == 1)
2597 res = syscall_fixup(tcp);
2598 if (res == 0)
2599 return res;
2600 if (res == 1)
2601 res = syscall_enter(tcp);
2602 if (res == 0)
2603 return res;
2604
2605 if (res != 1) {
2606 printleader(tcp);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002607 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002608 tcp_last = tcp;
2609 if (scno_good != 1)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002610 tprintf("????" /* anti-trigraph gap */ "(");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002611 else if (tcp->scno >= nsyscalls || tcp->scno < 0)
2612 tprintf("syscall_%lu(", tcp->scno);
2613 else
2614 tprintf("%s(", sysent[tcp->scno].sys_name);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002615 /*
2616 * " <unavailable>" will be added later by the code which
2617 * detects ptrace errors.
2618 */
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002619 tcp->flags |= TCB_INSYSCALL;
2620 return res;
2621 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002622
Roland McGrath17352792005-06-07 23:21:26 +00002623 switch (known_scno(tcp)) {
Roland McGrathd5bd7e62008-08-25 03:16:26 +00002624#ifdef SYS_socket_subcall
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002625 case SYS_socketcall:
2626 decode_subcall(tcp, SYS_socket_subcall,
2627 SYS_socket_nsubcalls, deref_style);
2628 break;
Roland McGrathd5bd7e62008-08-25 03:16:26 +00002629#endif
2630#ifdef SYS_ipc_subcall
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002631 case SYS_ipc:
2632 decode_subcall(tcp, SYS_ipc_subcall,
2633 SYS_ipc_nsubcalls, shift_style);
2634 break;
Roland McGrathd5bd7e62008-08-25 03:16:26 +00002635#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002636#ifdef SVR4
2637#ifdef SYS_pgrpsys_subcall
2638 case SYS_pgrpsys:
2639 decode_subcall(tcp, SYS_pgrpsys_subcall,
2640 SYS_pgrpsys_nsubcalls, shift_style);
2641 break;
2642#endif /* SYS_pgrpsys_subcall */
2643#ifdef SYS_sigcall_subcall
2644 case SYS_sigcall:
2645 decode_subcall(tcp, SYS_sigcall_subcall,
2646 SYS_sigcall_nsubcalls, mask_style);
2647 break;
2648#endif /* SYS_sigcall_subcall */
2649 case SYS_msgsys:
2650 decode_subcall(tcp, SYS_msgsys_subcall,
2651 SYS_msgsys_nsubcalls, shift_style);
2652 break;
2653 case SYS_shmsys:
2654 decode_subcall(tcp, SYS_shmsys_subcall,
2655 SYS_shmsys_nsubcalls, shift_style);
2656 break;
2657 case SYS_semsys:
2658 decode_subcall(tcp, SYS_semsys_subcall,
2659 SYS_semsys_nsubcalls, shift_style);
2660 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002661 case SYS_sysfs:
2662 decode_subcall(tcp, SYS_sysfs_subcall,
2663 SYS_sysfs_nsubcalls, shift_style);
2664 break;
2665 case SYS_spcall:
2666 decode_subcall(tcp, SYS_spcall_subcall,
2667 SYS_spcall_nsubcalls, shift_style);
2668 break;
2669#ifdef SYS_context_subcall
2670 case SYS_context:
2671 decode_subcall(tcp, SYS_context_subcall,
2672 SYS_context_nsubcalls, shift_style);
2673 break;
2674#endif /* SYS_context_subcall */
Wichert Akkerman8829a551999-06-11 13:18:40 +00002675#ifdef SYS_door_subcall
2676 case SYS_door:
2677 decode_subcall(tcp, SYS_door_subcall,
2678 SYS_door_nsubcalls, door_style);
2679 break;
2680#endif /* SYS_door_subcall */
John Hughesbdf48f52001-03-06 15:08:09 +00002681#ifdef SYS_kaio_subcall
2682 case SYS_kaio:
2683 decode_subcall(tcp, SYS_kaio_subcall,
2684 SYS_kaio_nsubcalls, shift_style);
2685 break;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002686#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002687#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002688#ifdef FREEBSD
2689 case SYS_msgsys:
2690 case SYS_shmsys:
2691 case SYS_semsys:
2692 decode_subcall(tcp, 0, 0, table_style);
2693 break;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002694#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002695#ifdef SUNOS4
2696 case SYS_semsys:
2697 decode_subcall(tcp, SYS_semsys_subcall,
2698 SYS_semsys_nsubcalls, shift_style);
2699 break;
2700 case SYS_msgsys:
2701 decode_subcall(tcp, SYS_msgsys_subcall,
2702 SYS_msgsys_nsubcalls, shift_style);
2703 break;
2704 case SYS_shmsys:
2705 decode_subcall(tcp, SYS_shmsys_subcall,
2706 SYS_shmsys_nsubcalls, shift_style);
2707 break;
2708#endif
2709 }
2710
2711 internal_syscall(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002712 if (tcp->scno >=0 && tcp->scno < nsyscalls && !(qual_flags[tcp->scno] & QUAL_TRACE)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002713 tcp->flags |= TCB_INSYSCALL;
2714 return 0;
2715 }
2716
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002717 if (cflag == CFLAG_ONLY_STATS) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002718 tcp->flags |= TCB_INSYSCALL;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002719 gettimeofday(&tcp->etime, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002720 return 0;
2721 }
2722
2723 printleader(tcp);
2724 tcp->flags &= ~TCB_REPRINT;
2725 tcp_last = tcp;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002726 if (tcp->scno >= nsyscalls || tcp->scno < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002727 tprintf("syscall_%lu(", tcp->scno);
2728 else
2729 tprintf("%s(", sysent[tcp->scno].sys_name);
Roland McGrath761b5d72002-12-15 23:58:31 +00002730 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002731 ((qual_flags[tcp->scno] & QUAL_RAW) && tcp->scno != SYS_exit))
2732 sys_res = printargs(tcp);
2733 else
2734 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2735 if (fflush(tcp->outf) == EOF)
2736 return -1;
2737 tcp->flags |= TCB_INSYSCALL;
2738 /* Measure the entrance time as late as possible to avoid errors. */
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002739 if (dtime || cflag)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002740 gettimeofday(&tcp->etime, NULL);
2741 return sys_res;
2742}
2743
2744int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002745trace_syscall(struct tcb *tcp)
2746{
2747 return exiting(tcp) ?
2748 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2749}
2750
2751int
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002752printargs(tcp)
2753struct tcb *tcp;
2754{
2755 if (entering(tcp)) {
2756 int i;
2757
2758 for (i = 0; i < tcp->u_nargs; i++)
2759 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
2760 }
2761 return 0;
2762}
2763
2764long
2765getrval2(tcp)
2766struct tcb *tcp;
2767{
2768 long val = -1;
2769
2770#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002771#if defined (SPARC) || defined (SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04002772 struct pt_regs regs;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002773 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002774 return -1;
Mike Frysinger8566c502009-10-12 11:05:14 -04002775 val = regs.u_regs[U_REG_O1];
Roland McGrath6b1d43e2003-03-31 01:05:01 +00002776#elif defined(SH)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002777 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
Roland McGrath6b1d43e2003-03-31 01:05:01 +00002778 return -1;
Roland McGrathb4ce1762004-03-01 20:30:48 +00002779#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002780 if (upeek(tcp, PT_R9, &val) < 0)
Roland McGrathb4ce1762004-03-01 20:30:48 +00002781 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002782#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002783#endif /* LINUX */
2784
2785#ifdef SUNOS4
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002786 if (upeek(tcp, uoff(u_rval2), &val) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002787 return -1;
2788#endif /* SUNOS4 */
2789
2790#ifdef SVR4
2791#ifdef SPARC
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002792 val = tcp->status.PR_REG[R_O1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002793#endif /* SPARC */
2794#ifdef I386
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002795 val = tcp->status.PR_REG[EDX];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002796#endif /* I386 */
Michal Ludvig0e035502002-09-23 15:41:01 +00002797#ifdef X86_64
2798 val = tcp->status.PR_REG[RDX];
2799#endif /* X86_64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002800#ifdef MIPS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002801 val = tcp->status.PR_REG[CTX_V1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002802#endif /* MIPS */
2803#endif /* SVR4 */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002804
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002805#ifdef FREEBSD
2806 struct reg regs;
2807 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
2808 val = regs.r_edx;
Roland McGrath761b5d72002-12-15 23:58:31 +00002809#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002810 return val;
2811}
2812
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +00002813#ifdef SUNOS4
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002814/*
2815 * Apparently, indirect system calls have already be converted by ptrace(2),
2816 * so if you see "indir" this program has gone astray.
2817 */
2818int
2819sys_indir(tcp)
2820struct tcb *tcp;
2821{
2822 int i, scno, nargs;
2823
2824 if (entering(tcp)) {
2825 if ((scno = tcp->u_arg[0]) > nsyscalls) {
2826 fprintf(stderr, "Bogus syscall: %u\n", scno);
2827 return 0;
2828 }
2829 nargs = sysent[scno].nargs;
2830 tprintf("%s", sysent[scno].sys_name);
2831 for (i = 0; i < nargs; i++)
2832 tprintf(", %#lx", tcp->u_arg[i+1]);
2833 }
2834 return 0;
2835}
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +00002836#endif /* SUNOS4 */
Dmitry V. Levin2e55ff42008-09-03 01:02:46 +00002837
2838int
2839is_restart_error(struct tcb *tcp)
2840{
2841#ifdef LINUX
2842 if (!syserror(tcp))
2843 return 0;
2844 switch (tcp->u_error) {
2845 case ERESTARTSYS:
2846 case ERESTARTNOINTR:
2847 case ERESTARTNOHAND:
2848 case ERESTART_RESTARTBLOCK:
2849 return 1;
2850 default:
2851 break;
2852 }
2853#endif /* LINUX */
2854 return 0;
2855}