blob: c2940c396d48babbefe361fa73b2165f223dea5e [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#if HAVE_ASM_REG_H
Roland McGrath6d1a65c2004-07-12 07:44:08 +000046#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman00a82ee2001-03-28 20:29:17 +000047# define fpq kernel_fpq
48# define fq kernel_fq
49# define fpu kernel_fpu
50#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000051#include <asm/reg.h>
Roland McGrath6d1a65c2004-07-12 07:44:08 +000052#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman00a82ee2001-03-28 20:29:17 +000053# undef fpq
54# undef fq
Roland McGrath761b5d72002-12-15 23:58:31 +000055# undef fpu
Wichert Akkerman00a82ee2001-03-28 20:29:17 +000056#endif
Wichert Akkerman9ce1a631999-08-29 23:15:07 +000057#endif
58
Wichert Akkerman15dea971999-10-06 13:06:34 +000059#ifdef HAVE_SYS_REG_H
60#include <sys/reg.h>
61#ifndef PTRACE_PEEKUSR
62# define PTRACE_PEEKUSR PTRACE_PEEKUSER
63#endif
Wichert Akkermanfaf72222000-02-19 23:59:03 +000064#elif defined(HAVE_LINUX_PTRACE_H)
65#undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000066# ifdef HAVE_STRUCT_IA64_FPREG
67# define ia64_fpreg XXX_ia64_fpreg
68# endif
69# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
70# define pt_all_user_regs XXX_pt_all_user_regs
71# endif
Wichert Akkermanfaf72222000-02-19 23:59:03 +000072#include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000073# undef ia64_fpreg
74# undef pt_all_user_regs
Wichert Akkerman15dea971999-10-06 13:06:34 +000075#endif
76
Roland McGrath6d1a65c2004-07-12 07:44:08 +000077#if defined (LINUX) && defined (SPARC64)
78# define r_pc r_tpc
79# undef PTRACE_GETREGS
80# define PTRACE_GETREGS PTRACE_GETREGS64
81# undef PTRACE_SETREGS
82# define PTRACE_SETREGS PTRACE_SETREGS64
83#endif /* LINUX && SPARC64 */
84
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000085#if defined(LINUX) && defined(IA64)
86# include <asm/ptrace_offsets.h>
87# include <asm/rse.h>
88#endif
89
Pavel Machekd8ae7e32000-02-01 17:17:25 +000090#define NR_SYSCALL_BASE 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000091#ifdef LINUX
92#ifndef ERESTARTSYS
93#define ERESTARTSYS 512
94#endif
95#ifndef ERESTARTNOINTR
96#define ERESTARTNOINTR 513
97#endif
98#ifndef ERESTARTNOHAND
99#define ERESTARTNOHAND 514 /* restart if no handler.. */
100#endif
101#ifndef ENOIOCTLCMD
102#define ENOIOCTLCMD 515 /* No ioctl command */
103#endif
Roland McGrath9c555e72003-07-09 09:47:59 +0000104#ifndef ERESTART_RESTARTBLOCK
105#define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
106#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000107#ifndef NSIG
108#define NSIG 32
109#endif
110#ifdef ARM
111#undef NSIG
112#define NSIG 32
Pavel Machekd8ae7e32000-02-01 17:17:25 +0000113#undef NR_SYSCALL_BASE
114#define NR_SYSCALL_BASE __NR_SYSCALL_BASE
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000115#endif
116#endif /* LINUX */
117
118#include "syscall.h"
119
120/* Define these shorthand notations to simplify the syscallent files. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000121#define TD TRACE_DESC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122#define TF TRACE_FILE
123#define TI TRACE_IPC
124#define TN TRACE_NETWORK
125#define TP TRACE_PROCESS
126#define TS TRACE_SIGNAL
127
Roland McGrathee36ce12004-09-04 03:53:10 +0000128static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000129#include "syscallent.h"
130};
Roland McGrathee36ce12004-09-04 03:53:10 +0000131static const int nsyscalls0 = sizeof sysent0 / sizeof sysent0[0];
Roland McGrath138c6a32006-01-12 09:50:49 +0000132int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000133
134#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000135static const struct sysent sysent1[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000136#include "syscallent1.h"
137};
Roland McGrathee36ce12004-09-04 03:53:10 +0000138static const int nsyscalls1 = sizeof sysent1 / sizeof sysent1[0];
Roland McGrath138c6a32006-01-12 09:50:49 +0000139int qual_flags1[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000140#endif /* SUPPORTED_PERSONALITIES >= 2 */
141
142#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000143static const struct sysent sysent2[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000144#include "syscallent2.h"
145};
Roland McGrathee36ce12004-09-04 03:53:10 +0000146static const int nsyscalls2 = sizeof sysent2 / sizeof sysent2[0];
Roland McGrath138c6a32006-01-12 09:50:49 +0000147int qual_flags2[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000148#endif /* SUPPORTED_PERSONALITIES >= 3 */
149
Roland McGrathee36ce12004-09-04 03:53:10 +0000150const struct sysent *sysent;
Roland McGrath138c6a32006-01-12 09:50:49 +0000151int *qual_flags;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000152int nsyscalls;
153
154/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000155#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000156#undef TF
157#undef TI
158#undef TN
159#undef TP
160#undef TS
161
Roland McGrathee36ce12004-09-04 03:53:10 +0000162static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000163#include "errnoent.h"
164};
Roland McGrathee36ce12004-09-04 03:53:10 +0000165static const int nerrnos0 = sizeof errnoent0 / sizeof errnoent0[0];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000166
167#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000168static const char *const errnoent1[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000169#include "errnoent1.h"
170};
Roland McGrathee36ce12004-09-04 03:53:10 +0000171static const int nerrnos1 = sizeof errnoent1 / sizeof errnoent1[0];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000172#endif /* SUPPORTED_PERSONALITIES >= 2 */
173
174#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000175static const char *const errnoent2[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000176#include "errnoent2.h"
177};
Roland McGrathee36ce12004-09-04 03:53:10 +0000178static const int nerrnos2 = sizeof errnoent2 / sizeof errnoent2[0];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000179#endif /* SUPPORTED_PERSONALITIES >= 3 */
180
Roland McGrathee36ce12004-09-04 03:53:10 +0000181const char *const *errnoent;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000182int nerrnos;
183
184int current_personality;
185
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000186#ifndef PERSONALITY0_WORDSIZE
187# define PERSONALITY0_WORDSIZE sizeof(long)
188#endif
189const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
190 PERSONALITY0_WORDSIZE,
191#if SUPPORTED_PERSONALITIES > 1
192 PERSONALITY1_WORDSIZE,
193#endif
194#if SUPPORTED_PERSONALITIES > 2
195 PERSONALITY2_WORDSIZE,
196#endif
197};;
198
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000199int
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000200set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000201{
202 switch (personality) {
203 case 0:
204 errnoent = errnoent0;
205 nerrnos = nerrnos0;
206 sysent = sysent0;
207 nsyscalls = nsyscalls0;
208 ioctlent = ioctlent0;
209 nioctlents = nioctlents0;
210 signalent = signalent0;
211 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000212 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000213 break;
214
215#if SUPPORTED_PERSONALITIES >= 2
216 case 1:
217 errnoent = errnoent1;
218 nerrnos = nerrnos1;
219 sysent = sysent1;
220 nsyscalls = nsyscalls1;
221 ioctlent = ioctlent1;
222 nioctlents = nioctlents1;
223 signalent = signalent1;
224 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000225 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000226 break;
227#endif /* SUPPORTED_PERSONALITIES >= 2 */
228
229#if SUPPORTED_PERSONALITIES >= 3
230 case 2:
231 errnoent = errnoent2;
232 nerrnos = nerrnos2;
233 sysent = sysent2;
234 nsyscalls = nsyscalls2;
235 ioctlent = ioctlent2;
236 nioctlents = nioctlents2;
237 signalent = signalent2;
238 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000239 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000240 break;
241#endif /* SUPPORTED_PERSONALITIES >= 3 */
242
243 default:
244 return -1;
245 }
246
247 current_personality = personality;
248 return 0;
249}
250
Roland McGrathe10e62a2004-09-04 04:20:43 +0000251
Roland McGrath9797ceb2002-12-30 10:23:00 +0000252static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000253
Roland McGrathe10e62a2004-09-04 04:20:43 +0000254static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000255 int bitflag;
256 char *option_name;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000257 int (*qualify)();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000258 char *argument_name;
259} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000260 { QUAL_TRACE, "trace", qual_syscall, "system call" },
261 { QUAL_TRACE, "t", qual_syscall, "system call" },
262 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
263 { QUAL_ABBREV, "a", qual_syscall, "system call" },
264 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
265 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
266 { QUAL_RAW, "raw", qual_syscall, "system call" },
267 { QUAL_RAW, "x", qual_syscall, "system call" },
268 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
269 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
270 { QUAL_SIGNAL, "s", qual_signal, "signal" },
271 { QUAL_FAULT, "fault", qual_fault, "fault" },
272 { QUAL_FAULT, "faults", qual_fault, "fault" },
273 { QUAL_FAULT, "m", qual_fault, "fault" },
274 { QUAL_READ, "read", qual_desc, "descriptor" },
275 { QUAL_READ, "reads", qual_desc, "descriptor" },
276 { QUAL_READ, "r", qual_desc, "descriptor" },
277 { QUAL_WRITE, "write", qual_desc, "descriptor" },
278 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
279 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000280 { 0, NULL, NULL, NULL },
281};
282
Roland McGrath9797ceb2002-12-30 10:23:00 +0000283static void
Roland McGrath138c6a32006-01-12 09:50:49 +0000284qualify_one(n, opt, not, pers)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000285 int n;
Roland McGrathe10e62a2004-09-04 04:20:43 +0000286 const struct qual_options *opt;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000287 int not;
Roland McGrath138c6a32006-01-12 09:50:49 +0000288 int pers;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000289{
Roland McGrath138c6a32006-01-12 09:50:49 +0000290 if (pers == 0 || pers < 0) {
291 if (not)
292 qual_flags0[n] &= ~opt->bitflag;
293 else
294 qual_flags0[n] |= opt->bitflag;
295 }
296
297#if SUPPORTED_PERSONALITIES >= 2
298 if (pers == 1 || pers < 0) {
299 if (not)
300 qual_flags1[n] &= ~opt->bitflag;
301 else
302 qual_flags1[n] |= opt->bitflag;
303 }
304#endif /* SUPPORTED_PERSONALITIES >= 2 */
305
306#if SUPPORTED_PERSONALITIES >= 3
307 if (pers == 2 || pers < 0) {
308 if (not)
309 qual_flags2[n] &= ~opt->bitflag;
310 else
311 qual_flags2[n] |= opt->bitflag;
312 }
313#endif /* SUPPORTED_PERSONALITIES >= 3 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000314}
315
316static int
Roland McGrath9797ceb2002-12-30 10:23:00 +0000317qual_syscall(s, opt, not)
318 char *s;
Roland McGrathe10e62a2004-09-04 04:20:43 +0000319 const struct qual_options *opt;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000320 int not;
321{
322 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000323 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000324
Roland McGrath48a035f2006-01-12 09:45:56 +0000325 if (isdigit((unsigned char)*s)) {
326 int i = atoi(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000327 if (i < 0 || i >= MAX_QUALS)
Roland McGrath48a035f2006-01-12 09:45:56 +0000328 return -1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000329 qualify_one(i, opt, not, -1);
Roland McGrath48a035f2006-01-12 09:45:56 +0000330 return 0;
331 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000332 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000333 if (strcmp(s, sysent0[i].sys_name) == 0) {
334 qualify_one(i, opt, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000335 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000336 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000337
338#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000339 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000340 if (strcmp(s, sysent1[i].sys_name) == 0) {
341 qualify_one(i, opt, not, 1);
342 rc = 0;
343 }
344#endif /* SUPPORTED_PERSONALITIES >= 2 */
345
346#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000347 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000348 if (strcmp(s, sysent2[i].sys_name) == 0) {
349 qualify_one(i, opt, not, 2);
350 rc = 0;
351 }
352#endif /* SUPPORTED_PERSONALITIES >= 3 */
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000353
Roland McGrathfe6b3522005-02-02 04:40:11 +0000354 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000355}
356
357static int
358qual_signal(s, opt, not)
359 char *s;
Roland McGrathe10e62a2004-09-04 04:20:43 +0000360 const struct qual_options *opt;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000361 int not;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000362{
363 int i;
364 char buf[32];
365
Roland McGrath48a035f2006-01-12 09:45:56 +0000366 if (isdigit((unsigned char)*s)) {
Roland McGrathfe6b3522005-02-02 04:40:11 +0000367 int signo = atoi(s);
368 if (signo < 0 || signo >= MAX_QUALS)
369 return -1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000370 qualify_one(signo, opt, not, -1);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000371 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000372 }
Roland McGrathd62b6712004-03-02 06:52:01 +0000373 if (strlen(s) >= sizeof buf)
Roland McGrathfe6b3522005-02-02 04:40:11 +0000374 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000375 strcpy(buf, s);
376 s = buf;
377 for (i = 0; s[i]; i++)
Wichert Akkerman2ee6e452000-02-18 15:36:12 +0000378 s[i] = toupper((unsigned char)(s[i]));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000379 if (strncmp(s, "SIG", 3) == 0)
380 s += 3;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000381 for (i = 0; i <= NSIG; i++)
382 if (strcmp(s, signame(i) + 3) == 0) {
Roland McGrath138c6a32006-01-12 09:50:49 +0000383 qualify_one(i, opt, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000384 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000385 }
Roland McGrath76421df2005-02-02 03:51:18 +0000386 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000387}
388
389static int
390qual_fault(s, opt, not)
391 char *s;
Roland McGrathe10e62a2004-09-04 04:20:43 +0000392 const struct qual_options *opt;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000393 int not;
394{
395 return -1;
396}
397
398static int
399qual_desc(s, opt, not)
400 char *s;
Roland McGrathe10e62a2004-09-04 04:20:43 +0000401 const struct qual_options *opt;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000402 int not;
403{
Roland McGrath48a035f2006-01-12 09:45:56 +0000404 if (isdigit((unsigned char)*s)) {
Roland McGrathfe6b3522005-02-02 04:40:11 +0000405 int desc = atoi(s);
406 if (desc < 0 || desc >= MAX_QUALS)
407 return -1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000408 qualify_one(desc, opt, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000409 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000410 }
411 return -1;
412}
413
414static int
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000415lookup_class(s)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000416 char *s;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000417{
418 if (strcmp(s, "file") == 0)
419 return TRACE_FILE;
420 if (strcmp(s, "ipc") == 0)
421 return TRACE_IPC;
422 if (strcmp(s, "network") == 0)
423 return TRACE_NETWORK;
424 if (strcmp(s, "process") == 0)
425 return TRACE_PROCESS;
426 if (strcmp(s, "signal") == 0)
427 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000428 if (strcmp(s, "desc") == 0)
429 return TRACE_DESC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000430 return -1;
431}
432
433void
434qualify(s)
435char *s;
436{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000437 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000438 int not;
439 char *p;
440 int i, n;
441
442 opt = &qual_options[0];
443 for (i = 0; (p = qual_options[i].option_name); i++) {
444 n = strlen(p);
445 if (strncmp(s, p, n) == 0 && s[n] == '=') {
446 opt = &qual_options[i];
447 s += n + 1;
448 break;
449 }
450 }
451 not = 0;
452 if (*s == '!') {
453 not = 1;
454 s++;
455 }
456 if (strcmp(s, "none") == 0) {
457 not = 1 - not;
458 s = "all";
459 }
460 if (strcmp(s, "all") == 0) {
461 for (i = 0; i < MAX_QUALS; i++) {
Roland McGrath138c6a32006-01-12 09:50:49 +0000462 qualify_one(i, opt, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000463 }
464 return;
465 }
466 for (i = 0; i < MAX_QUALS; i++) {
Roland McGrath138c6a32006-01-12 09:50:49 +0000467 qualify_one(i, opt, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000468 }
469 for (p = strtok(s, ","); p; p = strtok(NULL, ",")) {
470 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000471 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000472 if (sysent0[i].sys_flags & n)
473 qualify_one(i, opt, not, 0);
474
475#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000476 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000477 if (sysent1[i].sys_flags & n)
478 qualify_one(i, opt, not, 1);
479#endif /* SUPPORTED_PERSONALITIES >= 2 */
480
481#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000482 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000483 if (sysent2[i].sys_flags & n)
484 qualify_one(i, opt, not, 2);
485#endif /* SUPPORTED_PERSONALITIES >= 3 */
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000486
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000487 continue;
488 }
Roland McGrath9797ceb2002-12-30 10:23:00 +0000489 if (opt->qualify(p, opt, not)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000490 fprintf(stderr, "strace: invalid %s `%s'\n",
491 opt->argument_name, p);
492 exit(1);
493 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000494 }
495 return;
496}
497
498static void
499dumpio(tcp)
500struct tcb *tcp;
501{
502 if (syserror(tcp))
503 return;
504 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
505 return;
Roland McGrath17352792005-06-07 23:21:26 +0000506 switch (known_scno(tcp)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000507 case SYS_read:
Roland McGrathaa510622004-08-31 07:47:45 +0000508#ifdef SYS_pread64
509 case SYS_pread64:
510#endif
511#if defined SYS_pread && SYS_pread64 != SYS_pread
512 case SYS_pread:
513#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000514#ifdef SYS_recv
515 case SYS_recv:
Roland McGrath17352792005-06-07 23:21:26 +0000516#elif defined SYS_sub_recv
517 case SYS_sub_recv:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000518#endif
519#ifdef SYS_recvfrom
520 case SYS_recvfrom:
Roland McGrath17352792005-06-07 23:21:26 +0000521#elif defined SYS_sub_recvfrom
522 case SYS_sub_recvfrom:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000523#endif
524 if (qual_flags[tcp->u_arg[0]] & QUAL_READ)
525 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
526 break;
527 case SYS_write:
Roland McGrathaa510622004-08-31 07:47:45 +0000528#ifdef SYS_pwrite64
529 case SYS_pwrite64:
530#endif
531#if defined SYS_pwrite && SYS_pwrite64 != SYS_pwrite
532 case SYS_pwrite:
533#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000534#ifdef SYS_send
535 case SYS_send:
Roland McGrath17352792005-06-07 23:21:26 +0000536#elif defined SYS_sub_send
537 case SYS_sub_send:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000538#endif
539#ifdef SYS_sendto
540 case SYS_sendto:
Roland McGrath17352792005-06-07 23:21:26 +0000541#elif defined SYS_sub_sendto
542 case SYS_sub_sendto:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000543#endif
544 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE)
545 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
546 break;
John Hughes1d08dcf2001-07-10 13:48:44 +0000547#ifdef SYS_readv
548 case SYS_readv:
549 if (qual_flags[tcp->u_arg[0]] & QUAL_READ)
550 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
551 break;
552#endif
553#ifdef SYS_writev
554 case SYS_writev:
555
556 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE)
557 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
558 break;
559#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000560 }
561}
562
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000563#ifndef FREEBSD
Wichert Akkerman8829a551999-06-11 13:18:40 +0000564enum subcall_style { shift_style, deref_style, mask_style, door_style };
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000565#else /* FREEBSD */
566enum subcall_style { shift_style, deref_style, mask_style, door_style, table_style };
567
568struct subcall {
569 int call;
570 int nsubcalls;
571 int subcalls[5];
572};
573
Roland McGratha4d48532005-06-08 20:45:28 +0000574static const struct subcall subcalls_table[] = {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000575 { SYS_shmsys, 5, { SYS_shmat, SYS_shmctl, SYS_shmdt, SYS_shmget, SYS_shmctl } },
John Hughes61eeb552001-03-06 15:51:53 +0000576#ifdef SYS_semconfig
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000577 { SYS_semsys, 4, { SYS___semctl, SYS_semget, SYS_semop, SYS_semconfig } },
John Hughes61eeb552001-03-06 15:51:53 +0000578#else
579 { SYS_semsys, 3, { SYS___semctl, SYS_semget, SYS_semop } },
580#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000581 { SYS_msgsys, 4, { SYS_msgctl, SYS_msgget, SYS_msgsnd, SYS_msgrcv } },
582};
583#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000584
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000585#if !(defined(LINUX) && ( defined(ALPHA) || defined(MIPS) ))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000586
Roland McGratha4d48532005-06-08 20:45:28 +0000587static void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000588decode_subcall(tcp, subcall, nsubcalls, style)
589struct tcb *tcp;
590int subcall;
591int nsubcalls;
592enum subcall_style style;
593{
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000594 unsigned long addr, mask;
Michal Ludvig10a88d02002-10-07 14:31:00 +0000595 int i;
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000596 int size = personality_wordsize[current_personality];
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000597
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000598 switch (style) {
599 case shift_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000600 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
601 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000602 tcp->scno = subcall + tcp->u_arg[0];
603 if (sysent[tcp->scno].nargs != -1)
604 tcp->u_nargs = sysent[tcp->scno].nargs;
605 else
606 tcp->u_nargs--;
607 for (i = 0; i < tcp->u_nargs; i++)
608 tcp->u_arg[i] = tcp->u_arg[i + 1];
609 break;
610 case deref_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000611 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
612 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000613 tcp->scno = subcall + tcp->u_arg[0];
614 addr = tcp->u_arg[1];
615 for (i = 0; i < sysent[tcp->scno].nargs; i++) {
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000616 if (size == sizeof(int)) {
617 unsigned int arg;
618 if (umove(tcp, addr, &arg) < 0)
619 arg = 0;
620 tcp->u_arg[i] = arg;
621 }
622 else if (size == sizeof(long)) {
623 unsigned long arg;
624 if (umove(tcp, addr, &arg) < 0)
625 arg = 0;
626 tcp->u_arg[i] = arg;
627 }
628 else
629 abort();
630 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000631 }
632 tcp->u_nargs = sysent[tcp->scno].nargs;
633 break;
634 case mask_style:
635 mask = (tcp->u_arg[0] >> 8) & 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000636 for (i = 0; mask; i++)
637 mask >>= 1;
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000638 if (i >= nsubcalls)
639 return;
640 tcp->u_arg[0] &= 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000641 tcp->scno = subcall + i;
642 if (sysent[tcp->scno].nargs != -1)
643 tcp->u_nargs = sysent[tcp->scno].nargs;
644 break;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000645 case door_style:
646 /*
647 * Oh, yuck. The call code is the *sixth* argument.
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000648 * (don't you mean the *last* argument? - JH)
Wichert Akkerman8829a551999-06-11 13:18:40 +0000649 */
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000650 if (tcp->u_arg[5] < 0 || tcp->u_arg[5] >= nsubcalls)
651 return;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000652 tcp->scno = subcall + tcp->u_arg[5];
653 if (sysent[tcp->scno].nargs != -1)
654 tcp->u_nargs = sysent[tcp->scno].nargs;
655 else
656 tcp->u_nargs--;
657 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000658#ifdef FREEBSD
659 case table_style:
660 for (i = 0; i < sizeof(subcalls_table) / sizeof(struct subcall); i++)
661 if (subcalls_table[i].call == tcp->scno) break;
662 if (i < sizeof(subcalls_table) / sizeof(struct subcall) &&
663 tcp->u_arg[0] >= 0 && tcp->u_arg[0] < subcalls_table[i].nsubcalls) {
664 tcp->scno = subcalls_table[i].subcalls[tcp->u_arg[0]];
665 for (i = 0; i < tcp->u_nargs; i++)
666 tcp->u_arg[i] = tcp->u_arg[i + 1];
667 }
668 break;
669#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000670 }
671}
672#endif
673
674struct tcb *tcp_last = NULL;
675
676static int
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000677internal_syscall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000678{
679 /*
680 * We must always trace a few critical system calls in order to
681 * correctly support following forks in the presence of tracing
682 * qualifiers.
683 */
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000684 int (*func)();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000685
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000686 if (tcp->scno < 0 || tcp->scno >= nsyscalls)
687 return 0;
688
689 func = sysent[tcp->scno].sys_func;
690
691 if (sys_exit == func)
692 return internal_exit(tcp);
693
694 if ( sys_fork == func
695#if defined(FREEBSD) || defined(LINUX) || defined(SUNOS4)
696 || sys_vfork == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000697#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000698#if UNIXWARE > 2
699 || sys_rfork == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000700#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000701 )
702 return internal_fork(tcp);
703
704#if defined(LINUX) && (defined SYS_clone || defined SYS_clone2)
705 if (sys_clone == func)
706 return internal_clone(tcp);
Roland McGrathc74c0b72004-09-01 19:39:46 +0000707#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000708
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000709 if ( sys_execve == func
710#if defined(SPARC) || defined(SPARC64) || defined(SUNOS4)
711 || sys_execv == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000712#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000713#if UNIXWARE > 2
714 || sys_rexecve == func
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000715#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000716 )
717 return internal_exec(tcp);
718
719 if ( sys_waitpid == func
720 || sys_wait4 == func
721#if defined(SVR4) || defined(FREEBSD) || defined(SUNOS4)
722 || sys_wait == func
Roland McGrath923f7502003-01-09 06:53:27 +0000723#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000724#ifdef ALPHA
725 || sys_osf_wait4 == func
Roland McGrath08267b82004-02-20 22:56:43 +0000726#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000727 )
728 return internal_wait(tcp, 2);
729
730#if defined(LINUX) || defined(SVR4)
731 if (sys_waitid == func)
732 return internal_wait(tcp, 3);
733#endif
734
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000735 return 0;
736}
737
Wichert Akkermanc7926982000-04-10 22:22:31 +0000738
739#ifdef LINUX
740#if defined (I386)
741 static long eax;
742#elif defined (IA64)
743 long r8, r10, psr;
744 long ia32 = 0;
745#elif defined (POWERPC)
746 static long result,flags;
747#elif defined (M68K)
748 static int d0;
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000749#elif defined(BFIN)
750 static long r0;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000751#elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +0000752 static struct pt_regs regs;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000753#elif defined (ALPHA)
754 static long r0;
755 static long a3;
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000756#elif defined (SPARC) || defined (SPARC64)
Wichert Akkerman00a82ee2001-03-28 20:29:17 +0000757 static struct regs regs;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000758 static unsigned long trap;
Roland McGrath542c2c62008-05-20 01:11:56 +0000759#elif defined(LINUX_MIPSN32)
760 static long long a3;
761 static long long r2;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000762#elif defined(MIPS)
763 static long a3;
764 static long r2;
Michal Ludvig10a88d02002-10-07 14:31:00 +0000765#elif defined(S390) || defined(S390X)
Wichert Akkermanc7926982000-04-10 22:22:31 +0000766 static long gpr2;
767 static long pc;
Michal Ludvig882eda82002-11-11 12:50:47 +0000768 static long syscall_mode;
Wichert Akkermanc1652e22001-03-27 12:17:16 +0000769#elif defined(HPPA)
770 static long r28;
Wichert Akkermanccef6372002-05-01 16:39:22 +0000771#elif defined(SH)
772 static long r0;
Roland McGrathf5a47772003-06-26 22:40:42 +0000773#elif defined(SH64)
Roland McGrath0f87c492003-06-03 23:29:04 +0000774 static long r9;
Michal Ludvig0e035502002-09-23 15:41:01 +0000775#elif defined(X86_64)
776 static long rax;
Roland McGrath761b5d72002-12-15 23:58:31 +0000777#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000778#endif /* LINUX */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000779#ifdef FREEBSD
780 struct reg regs;
Roland McGrath761b5d72002-12-15 23:58:31 +0000781#endif /* FREEBSD */
Wichert Akkermanc7926982000-04-10 22:22:31 +0000782
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000783int
Pavel Machek4dc3b142000-02-01 17:58:41 +0000784get_scno(tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000785struct tcb *tcp;
786{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000787 long scno = 0;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000788#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000789 int pid = tcp->pid;
Roland McGrath761b5d72002-12-15 23:58:31 +0000790#endif /* !PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000791
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000792#ifdef LINUX
Michal Ludvig10a88d02002-10-07 14:31:00 +0000793#if defined(S390) || defined(S390X)
Roland McGrath96dc5142003-01-20 10:23:04 +0000794 if (tcp->flags & TCB_WAITEXECVE) {
795 /*
796 * When the execve system call completes successfully, the
797 * new process still has -ENOSYS (old style) or __NR_execve
798 * (new style) in gpr2. We cannot recover the scno again
799 * by disassembly, because the image that executed the
800 * syscall is gone now. Fortunately, we don't want it. We
801 * leave the flag set so that syscall_fixup can fake the
802 * result.
803 */
804 if (tcp->flags & TCB_INSYSCALL)
805 return 1;
806 /*
807 * This is the SIGTRAP after execve. We cannot try to read
808 * the system call here either.
809 */
810 tcp->flags &= ~TCB_WAITEXECVE;
811 return 0;
812 }
Roland McGrath2f924ca2003-06-26 22:23:28 +0000813
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000814 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Roland McGrath2f924ca2003-06-26 22:23:28 +0000815 return -1;
816
817 if (syscall_mode != -ENOSYS) {
818 /*
819 * Since kernel version 2.5.44 the scno gets passed in gpr2.
820 */
821 scno = syscall_mode;
822 } else {
Michal Ludvig882eda82002-11-11 12:50:47 +0000823 /*
824 * Old style of "passing" the scno via the SVC instruction.
825 */
826
827 long opcode, offset_reg, tmp;
828 void * svc_addr;
829 int gpr_offset[16] = {PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
830 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
831 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
832 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15};
Roland McGrath761b5d72002-12-15 23:58:31 +0000833
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000834 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000835 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000836 errno = 0;
Michal Ludvig882eda82002-11-11 12:50:47 +0000837 opcode = ptrace(PTRACE_PEEKTEXT, pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000838 if (errno) {
839 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000840 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000841 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000842
843 /*
844 * We have to check if the SVC got executed directly or via an
845 * EXECUTE instruction. In case of EXECUTE it is necessary to do
846 * instruction decoding to derive the system call number.
847 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
848 * so that this doesn't work if a SVC opcode is part of an EXECUTE
849 * opcode. Since there is no way to find out the opcode size this
850 * is the best we can do...
851 */
852
853 if ((opcode & 0xff00) == 0x0a00) {
854 /* SVC opcode */
855 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000856 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000857 else {
858 /* SVC got executed by EXECUTE instruction */
859
860 /*
861 * Do instruction decoding of EXECUTE. If you really want to
862 * understand this, read the Principles of Operations.
863 */
864 svc_addr = (void *) (opcode & 0xfff);
865
866 tmp = 0;
867 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000868 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000869 return -1;
870 svc_addr += tmp;
871
872 tmp = 0;
873 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000874 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000875 return -1;
876 svc_addr += tmp;
877
878 scno = ptrace(PTRACE_PEEKTEXT, pid, svc_addr, 0);
879 if (errno)
880 return -1;
881#if defined(S390X)
882 scno >>= 48;
883#else
884 scno >>= 16;
885#endif
886 tmp = 0;
887 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000888 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000889 return -1;
890
891 scno = (scno | tmp) & 0xff;
892 }
893 }
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +0000894#elif defined (POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000895 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000896 return -1;
897 if (!(tcp->flags & TCB_INSYSCALL)) {
898 /* Check if we return from execve. */
899 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
900 tcp->flags &= ~TCB_WAITEXECVE;
901 return 0;
902 }
903 }
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000904#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000905 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000906 return -1;
907 /* Check if we return from execve. */
908 if (tcp->flags & TCB_WAITEXECVE && tcp->flags & TCB_INSYSCALL)
909 tcp->flags &= ~(TCB_INSYSCALL | TCB_WAITEXECVE);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000910#elif defined (I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000911 if (upeek(tcp, 4*ORIG_EAX, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000912 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +0000913#elif defined (X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000914 if (upeek(tcp, 8*ORIG_RAX, &scno) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +0000915 return -1;
916
Roland McGrath761b5d72002-12-15 23:58:31 +0000917 if (!(tcp->flags & TCB_INSYSCALL)) {
918 static int currpers=-1;
Michal Ludvig0e035502002-09-23 15:41:01 +0000919 long val;
920
921 /* Check CS register value. On x86-64 linux it is:
922 * 0x33 for long mode (64 bit)
923 * 0x23 for compatibility mode (32 bit)
Roland McGrath761b5d72002-12-15 23:58:31 +0000924 * It takes only one ptrace and thus doesn't need
Michal Ludvig0e035502002-09-23 15:41:01 +0000925 * to be cached.
926 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000927 if (upeek(tcp, 8*CS, &val) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +0000928 return -1;
929 switch(val)
930 {
931 case 0x23: currpers = 1; break;
932 case 0x33: currpers = 0; break;
933 default:
934 fprintf(stderr, "Unknown value CS=0x%02X while "
935 "detecting personality of process "
936 "PID=%d\n", (int)val, pid);
937 currpers = current_personality;
938 break;
939 }
940#if 0
941 /* This version analyzes the opcode of a syscall instruction.
942 * (int 0x80 on i386 vs. syscall on x86-64)
943 * It works, but is too complicated.
944 */
945 unsigned long val, rip, i;
946
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000947 if(upeek(tcp, 8*RIP, &rip)<0)
Michal Ludvig0e035502002-09-23 15:41:01 +0000948 perror("upeek(RIP)");
Roland McGrath761b5d72002-12-15 23:58:31 +0000949
Michal Ludvig0e035502002-09-23 15:41:01 +0000950 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
951 rip-=2;
952 errno = 0;
953
Roland McGrath761b5d72002-12-15 23:58:31 +0000954 call = ptrace(PTRACE_PEEKTEXT,pid,(char *)rip,0);
955 if (errno)
956 printf("ptrace_peektext failed: %s\n",
Michal Ludvig0e035502002-09-23 15:41:01 +0000957 strerror(errno));
958 switch (call & 0xffff)
959 {
960 /* x86-64: syscall = 0x0f 0x05 */
961 case 0x050f: currpers = 0; break;
962 /* i386: int 0x80 = 0xcd 0x80 */
963 case 0x80cd: currpers = 1; break;
964 default:
965 currpers = current_personality;
Roland McGrath761b5d72002-12-15 23:58:31 +0000966 fprintf(stderr,
Michal Ludvig0e035502002-09-23 15:41:01 +0000967 "Unknown syscall opcode (0x%04X) while "
968 "detecting personality of process "
969 "PID=%d\n", (int)call, pid);
970 break;
971 }
972#endif
973 if(currpers != current_personality)
974 {
975 char *names[]={"64 bit", "32 bit"};
976 set_personality(currpers);
Roland McGrath761b5d72002-12-15 23:58:31 +0000977 printf("[ Process PID=%d runs in %s mode. ]\n",
Michal Ludvig0e035502002-09-23 15:41:01 +0000978 pid, names[current_personality]);
979 }
Roland McGrath761b5d72002-12-15 23:58:31 +0000980 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000981#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000982# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000983 if (upeek (tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000984 ia32 = (psr & IA64_PSR_IS) != 0;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000985 if (!(tcp->flags & TCB_INSYSCALL)) {
986 if (ia32) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000987 if (upeek(tcp, PT_R1, &scno) < 0) /* orig eax */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000988 return -1;
989 } else {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000990 if (upeek (tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000991 return -1;
992 }
Roland McGrathba954762003-03-05 06:29:06 +0000993 /* Check if we return from execve. */
994 if (tcp->flags & TCB_WAITEXECVE) {
995 tcp->flags &= ~TCB_WAITEXECVE;
996 return 0;
997 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000998 } else {
999 /* syscall in progress */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001000 if (upeek (tcp, PT_R8, &r8) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001001 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001002 if (upeek (tcp, PT_R10, &r10) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001003 return -1;
1004 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001005#elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001006 /*
1007 * Read complete register set in one go.
1008 */
1009 if (ptrace(PTRACE_GETREGS, pid, NULL, (void *)&regs) == -1)
1010 return -1;
1011
1012 /*
1013 * We only need to grab the syscall number on syscall entry.
1014 */
1015 if (regs.ARM_ip == 0) {
Roland McGrath9bc63402007-11-01 21:42:18 +00001016 if (!(tcp->flags & TCB_INSYSCALL)) {
1017 /* Check if we return from execve. */
1018 if (tcp->flags & TCB_WAITEXECVE) {
1019 tcp->flags &= ~TCB_WAITEXECVE;
1020 return 0;
1021 }
1022 }
1023
Roland McGrath0f87c492003-06-03 23:29:04 +00001024 /*
1025 * Note: we only deal with only 32-bit CPUs here.
1026 */
1027 if (regs.ARM_cpsr & 0x20) {
1028 /*
1029 * Get the Thumb-mode system call number
1030 */
1031 scno = regs.ARM_r7;
1032 } else {
1033 /*
1034 * Get the ARM-mode system call number
1035 */
1036 errno = 0;
1037 scno = ptrace(PTRACE_PEEKTEXT, pid, (void *)(regs.ARM_pc - 4), NULL);
1038 if (errno)
1039 return -1;
1040
1041 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
1042 tcp->flags &= ~TCB_WAITEXECVE;
1043 return 0;
1044 }
1045
Roland McGrathf691bd22006-04-25 07:34:41 +00001046 /* Handle the EABI syscall convention. We do not
1047 bother converting structures between the two
1048 ABIs, but basic functionality should work even
1049 if strace and the traced program have different
1050 ABIs. */
1051 if (scno == 0xef000000) {
1052 scno = regs.ARM_r7;
1053 } else {
1054 if ((scno & 0x0ff00000) != 0x0f900000) {
1055 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1056 scno);
1057 return -1;
1058 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001059
Roland McGrathf691bd22006-04-25 07:34:41 +00001060 /*
1061 * Fixup the syscall number
1062 */
1063 scno &= 0x000fffff;
1064 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001065 }
Roland McGrath56703312008-05-20 01:35:55 +00001066 if (scno & 0x0f0000) {
1067 /*
1068 * Handle ARM specific syscall
1069 */
1070 set_personality(1);
1071 scno &= 0x0000ffff;
1072 } else
1073 set_personality(0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001074
1075 if (tcp->flags & TCB_INSYSCALL) {
1076 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1077 tcp->flags &= ~TCB_INSYSCALL;
1078 }
1079 } else {
1080 if (!(tcp->flags & TCB_INSYSCALL)) {
1081 fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
1082 tcp->flags |= TCB_INSYSCALL;
1083 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001084 }
1085#elif defined (M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001086 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001087 return -1;
Roland McGrath542c2c62008-05-20 01:11:56 +00001088#elif defined (LINUX_MIPSN32)
1089 unsigned long long regs[38];
1090
1091 if (ptrace (PTRACE_GETREGS, pid, NULL, (long) &regs) < 0)
1092 return -1;
1093 a3 = regs[REG_A3];
1094 r2 = regs[REG_V0];
1095
1096 if(!(tcp->flags & TCB_INSYSCALL)) {
1097 scno = r2;
1098
1099 /* Check if we return from execve. */
1100 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1101 tcp->flags &= ~TCB_WAITEXECVE;
1102 return 0;
1103 }
1104
1105 if (scno < 0 || scno > nsyscalls) {
1106 if(a3 == 0 || a3 == -1) {
1107 if(debug)
1108 fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
1109 return 0;
1110 }
1111 }
1112 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001113#elif defined (MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001114 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkermanf90da011999-10-31 21:15:38 +00001115 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001116 if(!(tcp->flags & TCB_INSYSCALL)) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001117 if (upeek(tcp, REG_V0, &scno) < 0)
Wichert Akkermanf90da011999-10-31 21:15:38 +00001118 return -1;
1119
Roland McGrath542c2c62008-05-20 01:11:56 +00001120 /* Check if we return from execve. */
1121 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1122 tcp->flags &= ~TCB_WAITEXECVE;
1123 return 0;
1124 }
1125
Wichert Akkermanf90da011999-10-31 21:15:38 +00001126 if (scno < 0 || scno > nsyscalls) {
1127 if(a3 == 0 || a3 == -1) {
1128 if(debug)
1129 fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
1130 return 0;
1131 }
1132 }
1133 } else {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001134 if (upeek(tcp, REG_V0, &r2) < 0)
Wichert Akkermanf90da011999-10-31 21:15:38 +00001135 return -1;
1136 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001137#elif defined (ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001138 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001139 return -1;
1140
1141 if (!(tcp->flags & TCB_INSYSCALL)) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001142 if (upeek(tcp, REG_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001143 return -1;
1144
1145 /* Check if we return from execve. */
1146 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1147 tcp->flags &= ~TCB_WAITEXECVE;
1148 return 0;
1149 }
1150
1151 /*
1152 * Do some sanity checks to figure out if it's
1153 * really a syscall entry
1154 */
1155 if (scno < 0 || scno > nsyscalls) {
1156 if (a3 == 0 || a3 == -1) {
1157 if (debug)
1158 fprintf (stderr, "stray syscall exit: r0 = %ld\n", scno);
1159 return 0;
1160 }
1161 }
1162 }
1163 else {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001164 if (upeek(tcp, REG_R0, &r0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001165 return -1;
1166 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001167#elif defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001168 /* Everything we need is in the current register set. */
1169 if (ptrace(PTRACE_GETREGS,pid,(char *)&regs,0) < 0)
1170 return -1;
1171
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001172 /* If we are entering, then disassemble the syscall trap. */
1173 if (!(tcp->flags & TCB_INSYSCALL)) {
1174 /* Retrieve the syscall trap instruction. */
1175 errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001176 trap = ptrace(PTRACE_PEEKTEXT,pid,(char *)regs.r_pc,0);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001177#if defined(SPARC64)
1178 trap >>= 32;
1179#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001180 if (errno)
1181 return -1;
1182
1183 /* Disassemble the trap to see what personality to use. */
1184 switch (trap) {
1185 case 0x91d02010:
1186 /* Linux/SPARC syscall trap. */
1187 set_personality(0);
1188 break;
Wichert Akkermandacfb6e1999-06-03 14:21:07 +00001189 case 0x91d0206d:
1190 /* Linux/SPARC64 syscall trap. */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001191 set_personality(2);
1192 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001193 case 0x91d02000:
1194 /* SunOS syscall trap. (pers 1) */
1195 fprintf(stderr,"syscall: SunOS no support\n");
1196 return -1;
1197 case 0x91d02008:
1198 /* Solaris 2.x syscall trap. (per 2) */
1199 set_personality(1);
Roland McGrath761b5d72002-12-15 23:58:31 +00001200 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001201 case 0x91d02009:
1202 /* NetBSD/FreeBSD syscall trap. */
1203 fprintf(stderr,"syscall: NetBSD/FreeBSD not supported\n");
1204 return -1;
1205 case 0x91d02027:
1206 /* Solaris 2.x gettimeofday */
1207 set_personality(1);
1208 break;
1209 default:
1210 /* Unknown syscall trap. */
1211 if(tcp->flags & TCB_WAITEXECVE) {
1212 tcp->flags &= ~TCB_WAITEXECVE;
1213 return 0;
1214 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001215#if defined (SPARC64)
1216 fprintf(stderr,"syscall: unknown syscall trap %08lx %016lx\n", trap, regs.r_tpc);
1217#else
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001218 fprintf(stderr,"syscall: unknown syscall trap %08x %08x\n", trap, regs.r_pc);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001219#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001220 return -1;
1221 }
1222
1223 /* Extract the system call number from the registers. */
1224 if (trap == 0x91d02027)
1225 scno = 156;
1226 else
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001227 scno = regs.r_g1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001228 if (scno == 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001229 scno = regs.r_o0;
1230 memmove (&regs.r_o0, &regs.r_o1, 7*sizeof(regs.r_o0));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001231 }
1232 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001233#elif defined(HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001234 if (upeek(tcp, PT_GR20, &scno) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001235 return -1;
1236 if (!(tcp->flags & TCB_INSYSCALL)) {
1237 /* Check if we return from execve. */
1238 if ((tcp->flags & TCB_WAITEXECVE)) {
1239 tcp->flags &= ~TCB_WAITEXECVE;
1240 return 0;
1241 }
1242 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00001243#elif defined(SH)
1244 /*
1245 * In the new syscall ABI, the system call number is in R3.
1246 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001247 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
Wichert Akkermanccef6372002-05-01 16:39:22 +00001248 return -1;
1249
1250 if (scno < 0) {
1251 /* Odd as it may seem, a glibc bug has been known to cause
1252 glibc to issue bogus negative syscall numbers. So for
1253 our purposes, make strace print what it *should* have been */
1254 long correct_scno = (scno & 0xff);
1255 if (debug)
1256 fprintf(stderr,
Michal Ludvig53b320f2002-09-23 13:30:09 +00001257 "Detected glibc bug: bogus system call number = %ld, "
1258 "correcting to %ld\n",
Wichert Akkermanccef6372002-05-01 16:39:22 +00001259 scno,
1260 correct_scno);
1261 scno = correct_scno;
1262 }
1263
1264
1265 if (!(tcp->flags & TCB_INSYSCALL)) {
1266 /* Check if we return from execve. */
1267 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1268 tcp->flags &= ~TCB_WAITEXECVE;
1269 return 0;
1270 }
1271 }
Roland McGrathf5a47772003-06-26 22:40:42 +00001272#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001273 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001274 return -1;
1275 scno &= 0xFFFF;
1276
1277 if (!(tcp->flags & TCB_INSYSCALL)) {
1278 /* Check if we return from execve. */
1279 if (tcp->flags & TCB_WAITEXECVE) {
1280 tcp->flags &= ~TCB_WAITEXECVE;
1281 return 0;
1282 }
1283 }
Roland McGrathf5a47772003-06-26 22:40:42 +00001284#endif /* SH64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001285#endif /* LINUX */
1286#ifdef SUNOS4
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001287 if (upeek(tcp, uoff(u_arg[7]), &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001288 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001289#elif defined(SH)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001290 /* new syscall ABI returns result in R0 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001291 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001292 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001293#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001294 /* ABI defines result returned in r9 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001295 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001296 return -1;
1297
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001298#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001299#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001300#ifdef HAVE_PR_SYSCALL
John Hughes25299712001-03-06 10:10:06 +00001301 scno = tcp->status.PR_SYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001302#else /* !HAVE_PR_SYSCALL */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001303#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001304 scno = tcp->status.PR_WHAT;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001305#else /* FREEBSD */
1306 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1307 perror("pread");
1308 return -1;
1309 }
1310 switch (regs.r_eax) {
1311 case SYS_syscall:
1312 case SYS___syscall:
1313 pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int));
1314 break;
1315 default:
1316 scno = regs.r_eax;
1317 break;
1318 }
1319#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001320#endif /* !HAVE_PR_SYSCALL */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001321#endif /* USE_PROCFS */
Wichert Akkerman5ae21ea2000-05-01 01:53:59 +00001322 if (!(tcp->flags & TCB_INSYSCALL))
1323 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001324 return 1;
1325}
1326
Pavel Machek4dc3b142000-02-01 17:58:41 +00001327
Roland McGrath17352792005-06-07 23:21:26 +00001328long
1329known_scno(tcp)
1330struct tcb *tcp;
1331{
1332 long scno = tcp->scno;
1333 if (scno >= 0 && scno < nsyscalls && sysent[scno].native_scno != 0)
1334 scno = sysent[scno].native_scno;
1335 else
1336 scno += NR_SYSCALL_BASE;
1337 return scno;
1338}
1339
Roland McGratha4d48532005-06-08 20:45:28 +00001340static int
Pavel Machek4dc3b142000-02-01 17:58:41 +00001341syscall_fixup(tcp)
1342struct tcb *tcp;
1343{
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001344#ifdef USE_PROCFS
Roland McGrath17352792005-06-07 23:21:26 +00001345 int scno = known_scno(tcp);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001346
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001347 if (!(tcp->flags & TCB_INSYSCALL)) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001348 if (tcp->status.PR_WHY != PR_SYSENTRY) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001349 if (
1350 scno == SYS_fork
1351#ifdef SYS_vfork
1352 || scno == SYS_vfork
1353#endif /* SYS_vfork */
John Hughes4e36a812001-04-18 15:11:51 +00001354#ifdef SYS_fork1
1355 || scno == SYS_fork1
1356#endif /* SYS_fork1 */
1357#ifdef SYS_forkall
1358 || scno == SYS_forkall
1359#endif /* SYS_forkall */
1360#ifdef SYS_rfork1
1361 || scno == SYS_rfork1
1362#endif /* SYS_fork1 */
1363#ifdef SYS_rforkall
1364 || scno == SYS_rforkall
1365#endif /* SYS_rforkall */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001366 ) {
1367 /* We are returning in the child, fake it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001368 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001369 trace_syscall(tcp);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001370 tcp->status.PR_WHY = PR_SYSEXIT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001371 }
1372 else {
1373 fprintf(stderr, "syscall: missing entry\n");
1374 tcp->flags |= TCB_INSYSCALL;
1375 }
1376 }
1377 }
1378 else {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001379 if (tcp->status.PR_WHY != PR_SYSEXIT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001380 fprintf(stderr, "syscall: missing exit\n");
1381 tcp->flags &= ~TCB_INSYSCALL;
1382 }
1383 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001384#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001385#ifdef SUNOS4
1386 if (!(tcp->flags & TCB_INSYSCALL)) {
1387 if (scno == 0) {
1388 fprintf(stderr, "syscall: missing entry\n");
1389 tcp->flags |= TCB_INSYSCALL;
1390 }
1391 }
1392 else {
1393 if (scno != 0) {
1394 if (debug) {
1395 /*
1396 * This happens when a signal handler
1397 * for a signal which interrupted a
1398 * a system call makes another system call.
1399 */
1400 fprintf(stderr, "syscall: missing exit\n");
1401 }
1402 tcp->flags &= ~TCB_INSYSCALL;
1403 }
1404 }
1405#endif /* SUNOS4 */
1406#ifdef LINUX
1407#if defined (I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001408 if (upeek(tcp, 4*EAX, &eax) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001409 return -1;
1410 if (eax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1411 if (debug)
1412 fprintf(stderr, "stray syscall exit: eax = %ld\n", eax);
1413 return 0;
1414 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001415#elif defined (X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001416 if (upeek(tcp, 8*RAX, &rax) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00001417 return -1;
Roland McGrath998fac72004-06-23 01:40:45 +00001418 if (current_personality == 1)
1419 rax = (long int)(int)rax; /* sign extend from 32 bits */
Michal Ludvig0e035502002-09-23 15:41:01 +00001420 if (rax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1421 if (debug)
1422 fprintf(stderr, "stray syscall exit: rax = %ld\n", rax);
1423 return 0;
1424 }
Michal Ludvig10a88d02002-10-07 14:31:00 +00001425#elif defined (S390) || defined (S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001426 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001427 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001428 if (syscall_mode != -ENOSYS)
1429 syscall_mode = tcp->scno;
1430 if (gpr2 != syscall_mode && !(tcp->flags & TCB_INSYSCALL)) {
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001431 if (debug)
1432 fprintf(stderr, "stray syscall exit: gpr2 = %ld\n", gpr2);
1433 return 0;
1434 }
Roland McGrath96dc5142003-01-20 10:23:04 +00001435 else if (((tcp->flags & (TCB_INSYSCALL|TCB_WAITEXECVE))
1436 == (TCB_INSYSCALL|TCB_WAITEXECVE))
1437 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1438 /*
1439 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1440 * flag set for the post-execve SIGTRAP to see and reset.
1441 */
1442 gpr2 = 0;
1443 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001444#elif defined (POWERPC)
1445# define SO_MASK 0x10000000
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001446 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001447 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001448 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &result) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001449 return -1;
1450 if (flags & SO_MASK)
1451 result = -result;
1452#elif defined (M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001453 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001454 return -1;
1455 if (d0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1456 if (debug)
1457 fprintf(stderr, "stray syscall exit: d0 = %ld\n", d0);
1458 return 0;
1459 }
1460#elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001461 /*
1462 * Nothing required
1463 */
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001464#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001465 if (upeek(tcp, PT_R0, &r0) < 0)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001466 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001467#elif defined (HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001468 if (upeek(tcp, PT_GR28, &r28) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001469 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001470#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001471 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001472 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001473 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001474 return -1;
1475 if (ia32 && r8 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1476 if (debug)
1477 fprintf(stderr, "stray syscall exit: r8 = %ld\n", r8);
1478 return 0;
1479 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001480#endif
1481#endif /* LINUX */
Pavel Machek4dc3b142000-02-01 17:58:41 +00001482 return 1;
1483}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001484
Roland McGrathc1e45922008-05-27 23:18:29 +00001485#ifdef LINUX
1486/*
1487 * Check the syscall return value register value for whether it is
1488 * a negated errno code indicating an error, or a success return value.
1489 */
1490static inline int
1491is_negated_errno(unsigned long int val)
1492{
1493 unsigned long int max = -(long int) nerrnos;
1494 if (personality_wordsize[current_personality] < sizeof(val)) {
1495 val = (unsigned int) val;
1496 max = (unsigned int) max;
1497 }
1498 return val > max;
1499}
1500#endif
1501
Roland McGratha4d48532005-06-08 20:45:28 +00001502static int
Pavel Machek4dc3b142000-02-01 17:58:41 +00001503get_error(tcp)
1504struct tcb *tcp;
1505{
1506 int u_error = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001507#ifdef LINUX
Michal Ludvig10a88d02002-10-07 14:31:00 +00001508#if defined(S390) || defined(S390X)
Roland McGrathc1e45922008-05-27 23:18:29 +00001509 if (is_negated_errno(gpr2)) {
1510 tcp->u_rval = -1;
1511 u_error = -gpr2;
1512 }
1513 else {
1514 tcp->u_rval = gpr2;
1515 u_error = 0;
1516 }
Michal Ludvig10a88d02002-10-07 14:31:00 +00001517#else /* !S390 && !S390X */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001518#ifdef I386
Roland McGrathc1e45922008-05-27 23:18:29 +00001519 if (is_negated_errno(eax)) {
1520 tcp->u_rval = -1;
1521 u_error = -eax;
1522 }
1523 else {
1524 tcp->u_rval = eax;
1525 u_error = 0;
1526 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001527#else /* !I386 */
Michal Ludvig0e035502002-09-23 15:41:01 +00001528#ifdef X86_64
Roland McGrathc1e45922008-05-27 23:18:29 +00001529 if (is_negated_errno(rax)) {
1530 tcp->u_rval = -1;
1531 u_error = -rax;
1532 }
1533 else {
1534 tcp->u_rval = rax;
1535 u_error = 0;
1536 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001537#else
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001538#ifdef IA64
Roland McGrathc1e45922008-05-27 23:18:29 +00001539 if (ia32) {
1540 int err;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001541
Roland McGrathc1e45922008-05-27 23:18:29 +00001542 err = (int)r8;
1543 if (is_negated_errno(err)) {
1544 tcp->u_rval = -1;
1545 u_error = -err;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001546 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001547 else {
1548 tcp->u_rval = err;
1549 u_error = 0;
1550 }
1551 } else {
1552 if (r10) {
1553 tcp->u_rval = -1;
1554 u_error = r8;
1555 } else {
1556 tcp->u_rval = r8;
1557 u_error = 0;
1558 }
1559 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001560#else /* !IA64 */
Wichert Akkermanf90da011999-10-31 21:15:38 +00001561#ifdef MIPS
1562 if (a3) {
1563 tcp->u_rval = -1;
1564 u_error = r2;
1565 } else {
1566 tcp->u_rval = r2;
1567 u_error = 0;
1568 }
1569#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001570#ifdef POWERPC
Roland McGrathc1e45922008-05-27 23:18:29 +00001571 if (is_negated_errno(result)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001572 tcp->u_rval = -1;
1573 u_error = -result;
1574 }
1575 else {
1576 tcp->u_rval = result;
1577 u_error = 0;
1578 }
1579#else /* !POWERPC */
1580#ifdef M68K
Roland McGrathc1e45922008-05-27 23:18:29 +00001581 if (is_negated_errno(d0)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001582 tcp->u_rval = -1;
1583 u_error = -d0;
1584 }
1585 else {
1586 tcp->u_rval = d0;
1587 u_error = 0;
1588 }
1589#else /* !M68K */
1590#ifdef ARM
Roland McGrathc1e45922008-05-27 23:18:29 +00001591 if (is_negated_errno(regs.ARM_r0)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001592 tcp->u_rval = -1;
Roland McGrath0f87c492003-06-03 23:29:04 +00001593 u_error = -regs.ARM_r0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001594 }
1595 else {
Roland McGrath0f87c492003-06-03 23:29:04 +00001596 tcp->u_rval = regs.ARM_r0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001597 u_error = 0;
1598 }
1599#else /* !ARM */
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001600#ifdef BFIN
1601 if (is_negated_errno(r0)) {
1602 tcp->u_rval = -1;
1603 u_error = -r0;
1604 } else {
1605 tcp->u_rval = r0;
1606 u_error = 0;
1607 }
1608#else /* !BFIN */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001609#ifdef ALPHA
1610 if (a3) {
1611 tcp->u_rval = -1;
1612 u_error = r0;
1613 }
1614 else {
1615 tcp->u_rval = r0;
1616 u_error = 0;
1617 }
1618#else /* !ALPHA */
1619#ifdef SPARC
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001620 if (regs.r_psr & PSR_C) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001621 tcp->u_rval = -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001622 u_error = regs.r_o0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001623 }
1624 else {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001625 tcp->u_rval = regs.r_o0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001626 u_error = 0;
1627 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001628#else /* !SPARC */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001629#ifdef SPARC64
1630 if (regs.r_tstate & 0x1100000000UL) {
1631 tcp->u_rval = -1;
1632 u_error = regs.r_o0;
1633 }
1634 else {
1635 tcp->u_rval = regs.r_o0;
1636 u_error = 0;
1637 }
1638#else /* !SPARC64 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001639#ifdef HPPA
Roland McGrathc1e45922008-05-27 23:18:29 +00001640 if (is_negated_errno(r28)) {
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001641 tcp->u_rval = -1;
1642 u_error = -r28;
1643 }
1644 else {
1645 tcp->u_rval = r28;
1646 u_error = 0;
1647 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00001648#else
1649#ifdef SH
Roland McGrathc1e45922008-05-27 23:18:29 +00001650 /* interpret R0 as return value or error number */
1651 if (is_negated_errno(r0)) {
1652 tcp->u_rval = -1;
1653 u_error = -r0;
1654 }
1655 else {
1656 tcp->u_rval = r0;
1657 u_error = 0;
1658 }
Roland McGrathe1e584b2003-06-02 19:18:58 +00001659#else
Roland McGrathf5a47772003-06-26 22:40:42 +00001660#ifdef SH64
Roland McGrathe1e584b2003-06-02 19:18:58 +00001661 /* interpret result as return value or error number */
Roland McGrathc1e45922008-05-27 23:18:29 +00001662 if (is_negated_errno(r9)) {
Roland McGrathe1e584b2003-06-02 19:18:58 +00001663 tcp->u_rval = -1;
1664 u_error = -r9;
1665 }
1666 else {
1667 tcp->u_rval = r9;
1668 u_error = 0;
1669 }
Roland McGrathf5a47772003-06-26 22:40:42 +00001670#endif /* SH64 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001671#endif /* SH */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001672#endif /* HPPA */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001673#endif /* SPARC */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001674#endif /* SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001675#endif /* ALPHA */
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001676#endif /* BFIN */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677#endif /* ARM */
1678#endif /* M68K */
1679#endif /* POWERPC */
Wichert Akkermanf90da011999-10-31 21:15:38 +00001680#endif /* MIPS */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001681#endif /* IA64 */
Michal Ludvig0e035502002-09-23 15:41:01 +00001682#endif /* X86_64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001683#endif /* I386 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001684#endif /* S390 || S390X */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001685#endif /* LINUX */
1686#ifdef SUNOS4
1687 /* get error code from user struct */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001688 if (upeek(tcp, uoff(u_error), &u_error) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001689 return -1;
1690 u_error >>= 24; /* u_error is a char */
1691
1692 /* get system call return value */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001693 if (upeek(tcp, uoff(u_rval1), &tcp->u_rval) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001694 return -1;
1695#endif /* SUNOS4 */
1696#ifdef SVR4
1697#ifdef SPARC
1698 /* Judicious guessing goes a long way. */
1699 if (tcp->status.pr_reg[R_PSR] & 0x100000) {
1700 tcp->u_rval = -1;
1701 u_error = tcp->status.pr_reg[R_O0];
1702 }
1703 else {
1704 tcp->u_rval = tcp->status.pr_reg[R_O0];
1705 u_error = 0;
1706 }
1707#endif /* SPARC */
1708#ifdef I386
1709 /* Wanna know how to kill an hour single-stepping? */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001710 if (tcp->status.PR_REG[EFL] & 0x1) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001711 tcp->u_rval = -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001712 u_error = tcp->status.PR_REG[EAX];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001713 }
1714 else {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001715 tcp->u_rval = tcp->status.PR_REG[EAX];
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001716#ifdef HAVE_LONG_LONG
1717 tcp->u_lrval =
1718 ((unsigned long long) tcp->status.PR_REG[EDX] << 32) +
1719 tcp->status.PR_REG[EAX];
1720#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001721 u_error = 0;
1722 }
1723#endif /* I386 */
Michal Ludvig0e035502002-09-23 15:41:01 +00001724#ifdef X86_64
1725 /* Wanna know how to kill an hour single-stepping? */
1726 if (tcp->status.PR_REG[EFLAGS] & 0x1) {
1727 tcp->u_rval = -1;
1728 u_error = tcp->status.PR_REG[RAX];
1729 }
1730 else {
1731 tcp->u_rval = tcp->status.PR_REG[RAX];
1732 u_error = 0;
1733 }
1734#endif /* X86_64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001735#ifdef MIPS
1736 if (tcp->status.pr_reg[CTX_A3]) {
1737 tcp->u_rval = -1;
1738 u_error = tcp->status.pr_reg[CTX_V0];
1739 }
1740 else {
1741 tcp->u_rval = tcp->status.pr_reg[CTX_V0];
1742 u_error = 0;
1743 }
1744#endif /* MIPS */
1745#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001746#ifdef FREEBSD
1747 if (regs.r_eflags & PSL_C) {
1748 tcp->u_rval = -1;
1749 u_error = regs.r_eax;
1750 } else {
1751 tcp->u_rval = regs.r_eax;
1752 tcp->u_lrval =
1753 ((unsigned long long) regs.r_edx << 32) + regs.r_eax;
1754 u_error = 0;
1755 }
Roland McGrath761b5d72002-12-15 23:58:31 +00001756#endif /* FREEBSD */
Pavel Machek4dc3b142000-02-01 17:58:41 +00001757 tcp->u_error = u_error;
1758 return 1;
1759}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001760
Roland McGrathb69f81b2002-12-21 23:25:18 +00001761int
1762force_result(tcp, error, rval)
1763 struct tcb *tcp;
1764 int error;
1765 long rval;
1766{
1767#ifdef LINUX
1768#if defined(S390) || defined(S390X)
1769 gpr2 = error ? -error : rval;
Roland McGrathb69f81b2002-12-21 23:25:18 +00001770 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_GPR2, gpr2) < 0)
1771 return -1;
1772#else /* !S390 && !S390X */
1773#ifdef I386
1774 eax = error ? -error : rval;
1775 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(EAX * 4), eax) < 0)
1776 return -1;
1777#else /* !I386 */
1778#ifdef X86_64
1779 rax = error ? -error : rval;
Roland McGrath998fac72004-06-23 01:40:45 +00001780 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(RAX * 8), rax) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001781 return -1;
1782#else
1783#ifdef IA64
1784 if (ia32) {
1785 r8 = error ? -error : rval;
1786 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0)
1787 return -1;
1788 }
1789 else {
1790 if (error) {
1791 r8 = error;
1792 r10 = -1;
1793 }
1794 else {
1795 r8 = rval;
1796 r10 = 0;
1797 }
1798 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0 ||
1799 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R10), r10) < 0)
1800 return -1;
1801 }
1802#else /* !IA64 */
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001803#ifdef BFIN
1804 r0 = error ? -error : rval;
1805 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_R0, r0) < 0)
1806 return -1;
1807#else /* !BFIN */
Roland McGrathb69f81b2002-12-21 23:25:18 +00001808#ifdef MIPS
1809 if (error) {
1810 r2 = error;
1811 a3 = -1;
1812 }
1813 else {
1814 r2 = rval;
1815 a3 = 0;
1816 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001817 /* PTRACE_POKEUSER is OK even for n32 since rval is only a long. */
Roland McGrathb69f81b2002-12-21 23:25:18 +00001818 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1819 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), r2) < 0)
1820 return -1;
1821#else
1822#ifdef POWERPC
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001823 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001824 return -1;
1825 if (error) {
1826 flags |= SO_MASK;
1827 result = error;
1828 }
1829 else {
1830 flags &= ~SO_MASK;
1831 result = rval;
1832 }
Roland McGratheb285352003-01-14 09:59:00 +00001833 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_CCR), flags) < 0 ||
1834 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_R3), result) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001835 return -1;
1836#else /* !POWERPC */
1837#ifdef M68K
1838 d0 = error ? -error : rval;
1839 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_D0), d0) < 0)
1840 return -1;
1841#else /* !M68K */
1842#ifdef ARM
Roland McGrath7c051d22003-06-26 22:29:32 +00001843 regs.ARM_r0 = error ? -error : rval;
1844 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*0), regs.ARM_r0) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001845 return -1;
1846#else /* !ARM */
1847#ifdef ALPHA
1848 if (error) {
1849 a3 = -1;
1850 r0 = error;
1851 }
1852 else {
1853 a3 = 0;
1854 r0 = rval;
1855 }
1856 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1857 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R0), r0) < 0)
1858 return -1;
1859#else /* !ALPHA */
1860#ifdef SPARC
1861 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1862 return -1;
1863 if (error) {
1864 regs.r_psr |= PSR_C;
1865 regs.r_o0 = error;
1866 }
1867 else {
1868 regs.r_psr &= ~PSR_C;
1869 regs.r_o0 = rval;
1870 }
1871 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1872 return -1;
1873#else /* !SPARC */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001874#ifdef SPARC64
1875 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1876 return -1;
1877 if (error) {
1878 regs.r_tstate |= 0x1100000000UL;
1879 regs.r_o0 = error;
1880 }
1881 else {
1882 regs.r_tstate &= ~0x1100000000UL;
1883 regs.r_o0 = rval;
1884 }
1885 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1886 return -1;
1887#else /* !SPARC64 */
Roland McGrathb69f81b2002-12-21 23:25:18 +00001888#ifdef HPPA
1889 r28 = error ? -error : rval;
1890 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR28), r28) < 0)
1891 return -1;
1892#else
1893#ifdef SH
1894 r0 = error ? -error : rval;
1895 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*REG_REG0), r0) < 0)
1896 return -1;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001897#else
Roland McGrathf5a47772003-06-26 22:40:42 +00001898#ifdef SH64
Roland McGrathe1e584b2003-06-02 19:18:58 +00001899 r9 = error ? -error : rval;
1900 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_GENERAL(9), r9) < 0)
1901 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001902#endif /* SH64 */
Roland McGrathb69f81b2002-12-21 23:25:18 +00001903#endif /* SH */
1904#endif /* HPPA */
1905#endif /* SPARC */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001906#endif /* SPARC64 */
Roland McGrathb69f81b2002-12-21 23:25:18 +00001907#endif /* ALPHA */
1908#endif /* ARM */
1909#endif /* M68K */
1910#endif /* POWERPC */
1911#endif /* MIPS */
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001912#endif /* BFIN */
Roland McGrathb69f81b2002-12-21 23:25:18 +00001913#endif /* IA64 */
1914#endif /* X86_64 */
1915#endif /* I386 */
1916#endif /* S390 || S390X */
1917#endif /* LINUX */
1918#ifdef SUNOS4
1919 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_error),
1920 error << 24) < 0 ||
1921 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_rval1), rval) < 0)
1922 return -1;
1923#endif /* SUNOS4 */
1924#ifdef SVR4
1925 /* XXX no clue */
1926 return -1;
1927#endif /* SVR4 */
1928#ifdef FREEBSD
1929 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1930 perror("pread");
1931 return -1;
1932 }
1933 if (error) {
1934 regs.r_eflags |= PSL_C;
1935 regs.r_eax = error;
1936 }
1937 else {
1938 regs.r_eflags &= ~PSL_C;
1939 regs.r_eax = rval;
1940 }
1941 if (pwrite(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1942 perror("pwrite");
1943 return -1;
1944 }
1945#endif /* FREEBSD */
1946
1947 /* All branches reach here on success (only). */
1948 tcp->u_error = error;
1949 tcp->u_rval = rval;
1950 return 0;
1951}
1952
Roland McGratha4d48532005-06-08 20:45:28 +00001953static int
1954syscall_enter(tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001955struct tcb *tcp;
1956{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001957#ifdef LINUX
Michal Ludvig10a88d02002-10-07 14:31:00 +00001958#if defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001959 {
1960 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001961 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1962 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00001963 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001964 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001965 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001966 if (upeek(tcp,i==0 ? PT_ORIGGPR2:PT_GPR2+i*sizeof(long), &tcp->u_arg[i]) < 0)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001967 return -1;
1968 }
1969 }
1970#elif defined (ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001971 {
1972 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001973 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1974 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00001975 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001976 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001977 for (i = 0; i < tcp->u_nargs; i++) {
Wichert Akkermanb859bea1999-04-18 22:50:50 +00001978 /* WTA: if scno is out-of-bounds this will bomb. Add range-check
1979 * for scno somewhere above here!
1980 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001981 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001982 return -1;
1983 }
1984 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001985#elif defined (IA64)
1986 {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001987 if (!ia32) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00001988 unsigned long *out0, cfm, sof, sol, i;
1989 long rbs_end;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001990 /* be backwards compatible with kernel < 2.4.4... */
1991# ifndef PT_RBS_END
1992# define PT_RBS_END PT_AR_BSP
1993# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001994
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001995 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001996 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001997 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001998 return -1;
1999
2000 sof = (cfm >> 0) & 0x7f;
2001 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002002 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002003
2004 if (tcp->scno >= 0 && tcp->scno < nsyscalls
2005 && sysent[tcp->scno].nargs != -1)
2006 tcp->u_nargs = sysent[tcp->scno].nargs;
2007 else
2008 tcp->u_nargs = MAX_ARGS;
2009 for (i = 0; i < tcp->u_nargs; ++i) {
2010 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
2011 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
2012 return -1;
2013 }
2014 } else {
2015 int i;
2016
2017 if (/* EBX = out0 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002018 upeek(tcp, PT_R11, (long *) &tcp->u_arg[0]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002019 /* ECX = out1 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002020 || upeek(tcp, PT_R9, (long *) &tcp->u_arg[1]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002021 /* EDX = out2 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002022 || upeek(tcp, PT_R10, (long *) &tcp->u_arg[2]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002023 /* ESI = out3 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002024 || upeek(tcp, PT_R14, (long *) &tcp->u_arg[3]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002025 /* EDI = out4 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002026 || upeek(tcp, PT_R15, (long *) &tcp->u_arg[4]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002027 /* EBP = out5 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002028 || upeek(tcp, PT_R13, (long *) &tcp->u_arg[5]) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002029 return -1;
2030
2031 for (i = 0; i < 6; ++i)
2032 /* truncate away IVE sign-extension */
2033 tcp->u_arg[i] &= 0xffffffff;
2034
2035 if (tcp->scno >= 0 && tcp->scno < nsyscalls
2036 && sysent[tcp->scno].nargs != -1)
2037 tcp->u_nargs = sysent[tcp->scno].nargs;
2038 else
2039 tcp->u_nargs = 5;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002040 }
2041 }
Roland McGrath542c2c62008-05-20 01:11:56 +00002042#elif defined (LINUX_MIPSN32) || defined (LINUX_MIPSN64)
2043 /* N32 and N64 both use up to six registers. */
2044 {
2045 unsigned long long regs[38];
2046 int i, nargs;
2047
2048 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2049 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrathc1e45922008-05-27 23:18:29 +00002050 else
Roland McGrath542c2c62008-05-20 01:11:56 +00002051 nargs = tcp->u_nargs = MAX_ARGS;
2052
2053 if (ptrace (PTRACE_GETREGS, pid, NULL, (long) &regs) < 0)
2054 return -1;
2055
2056 for(i = 0; i < nargs; i++) {
2057 tcp->u_arg[i] = regs[REG_A0 + i];
2058# if defined (LINUX_MIPSN32)
2059 tcp->ext_arg[i] = regs[REG_A0 + i];
2060# endif
2061 }
2062 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00002063#elif defined (MIPS)
2064 {
2065 long sp;
2066 int i, nargs;
2067
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002068 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2069 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002070 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002071 nargs = tcp->u_nargs = MAX_ARGS;
Wichert Akkermanf90da011999-10-31 21:15:38 +00002072 if(nargs > 4) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002073 if(upeek(tcp, REG_SP, &sp) < 0)
Wichert Akkermanf90da011999-10-31 21:15:38 +00002074 return -1;
2075 for(i = 0; i < 4; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002076 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i])<0)
Wichert Akkermanf90da011999-10-31 21:15:38 +00002077 return -1;
2078 }
2079 umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]),
2080 (char *)(tcp->u_arg + 4));
2081 } else {
2082 for(i = 0; i < nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002083 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkermanf90da011999-10-31 21:15:38 +00002084 return -1;
2085 }
2086 }
2087 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002088#elif defined (POWERPC)
Roland McGrath761b5d72002-12-15 23:58:31 +00002089#ifndef PT_ORIG_R3
2090#define PT_ORIG_R3 34
2091#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002092 {
2093 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002094 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2095 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002096 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002097 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002098 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002099 if (upeek(tcp, (i==0) ?
Roland McGratheb285352003-01-14 09:59:00 +00002100 (sizeof(unsigned long)*PT_ORIG_R3) :
2101 ((i+PT_R3)*sizeof(unsigned long)),
2102 &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002103 return -1;
2104 }
2105 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002106#elif defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002107 {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002108 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002109
2110 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2111 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002112 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002113 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002114 for (i = 0; i < tcp->u_nargs; i++)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002115 tcp->u_arg[i] = *((&regs.r_o0) + i);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002116 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002117#elif defined (HPPA)
2118 {
2119 int i;
2120
2121 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2122 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002123 else
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002124 tcp->u_nargs = MAX_ARGS;
2125 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002126 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002127 return -1;
2128 }
2129 }
Roland McGrath0f87c492003-06-03 23:29:04 +00002130#elif defined(ARM)
2131 {
2132 int i;
2133
2134 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2135 tcp->u_nargs = sysent[tcp->scno].nargs;
2136 else
2137 tcp->u_nargs = MAX_ARGS;
2138 for (i = 0; i < tcp->u_nargs; i++)
2139 tcp->u_arg[i] = regs.uregs[i];
2140 }
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00002141#elif defined(BFIN)
2142 {
2143 int i;
2144 int argreg[] = {PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5};
2145
2146 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2147 tcp->u_nargs = sysent[tcp->scno].nargs;
2148 else
2149 tcp->u_nargs = sizeof(argreg) / sizeof(argreg[0]);
2150
2151 for (i = 0; i < tcp->u_nargs; ++i)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002152 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00002153 return -1;
2154 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00002155#elif defined(SH)
2156 {
Roland McGrath761b5d72002-12-15 23:58:31 +00002157 int i;
Wichert Akkermanccef6372002-05-01 16:39:22 +00002158 static int syscall_regs[] = {
2159 REG_REG0+4, REG_REG0+5, REG_REG0+6, REG_REG0+7,
2160 REG_REG0, REG_REG0+1, REG_REG0+2
2161 };
2162
2163 tcp->u_nargs = sysent[tcp->scno].nargs;
2164 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002165 if (upeek(tcp, 4*syscall_regs[i], &tcp->u_arg[i]) < 0)
Wichert Akkermanccef6372002-05-01 16:39:22 +00002166 return -1;
2167 }
2168 }
Roland McGrathf5a47772003-06-26 22:40:42 +00002169#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00002170 {
2171 int i;
2172 /* Registers used by SH5 Linux system calls for parameters */
2173 static int syscall_regs[] = { 2, 3, 4, 5, 6, 7 };
2174
2175 /*
2176 * TODO: should also check that the number of arguments encoded
2177 * in the trap number matches the number strace expects.
2178 */
2179 /*
2180 assert(sysent[tcp->scno].nargs <
2181 sizeof(syscall_regs)/sizeof(syscall_regs[0]));
2182 */
2183
2184 tcp->u_nargs = sysent[tcp->scno].nargs;
2185 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002186 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00002187 return -1;
2188 }
2189 }
2190
Michal Ludvig0e035502002-09-23 15:41:01 +00002191#elif defined(X86_64)
2192 {
2193 int i;
2194 static int argreg[SUPPORTED_PERSONALITIES][MAX_ARGS] = {
2195 {RDI,RSI,RDX,R10,R8,R9}, /* x86-64 ABI */
Roland McGrath5a9c6ad2005-02-02 03:06:52 +00002196 {RBX,RCX,RDX,RSI,RDI,RBP} /* i386 ABI */
Michal Ludvig0e035502002-09-23 15:41:01 +00002197 };
Roland McGrath761b5d72002-12-15 23:58:31 +00002198
Michal Ludvig0e035502002-09-23 15:41:01 +00002199 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2200 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002201 else
Michal Ludvig0e035502002-09-23 15:41:01 +00002202 tcp->u_nargs = MAX_ARGS;
2203 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002204 if (upeek(tcp, argreg[current_personality][i]*8, &tcp->u_arg[i]) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00002205 return -1;
2206 }
2207 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00002208#else /* Other architecture (like i386) (32bits specific) */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002209 {
2210 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002211 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2212 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002213 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002214 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002215 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002216 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002217 return -1;
2218 }
2219 }
Roland McGrath761b5d72002-12-15 23:58:31 +00002220#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002221#endif /* LINUX */
2222#ifdef SUNOS4
2223 {
2224 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002225 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2226 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002227 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002228 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002229 for (i = 0; i < tcp->u_nargs; i++) {
2230 struct user *u;
2231
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002232 if (upeek(tcp, uoff(u_arg[0]) +
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002233 (i*sizeof(u->u_arg[0])), &tcp->u_arg[i]) < 0)
2234 return -1;
2235 }
2236 }
2237#endif /* SUNOS4 */
2238#ifdef SVR4
2239#ifdef MIPS
2240 /*
2241 * SGI is broken: even though it has pr_sysarg, it doesn't
2242 * set them on system call entry. Get a clue.
2243 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002244 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002245 tcp->u_nargs = sysent[tcp->scno].nargs;
2246 else
2247 tcp->u_nargs = tcp->status.pr_nsysarg;
2248 if (tcp->u_nargs > 4) {
2249 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2250 4*sizeof(tcp->u_arg[0]));
2251 umoven(tcp, tcp->status.pr_reg[CTX_SP] + 16,
2252 (tcp->u_nargs - 4)*sizeof(tcp->u_arg[0]), (char *) (tcp->u_arg + 4));
2253 }
2254 else {
2255 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2256 tcp->u_nargs*sizeof(tcp->u_arg[0]));
2257 }
John Hughes25299712001-03-06 10:10:06 +00002258#elif UNIXWARE >= 2
2259 /*
2260 * Like SGI, UnixWare doesn't set pr_sysarg until system call exit
2261 */
2262 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2263 tcp->u_nargs = sysent[tcp->scno].nargs;
2264 else
2265 tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;
2266 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
2267 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2268#elif defined (HAVE_PR_SYSCALL)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002269 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002270 tcp->u_nargs = sysent[tcp->scno].nargs;
2271 else
2272 tcp->u_nargs = tcp->status.pr_nsysarg;
2273 {
2274 int i;
2275 for (i = 0; i < tcp->u_nargs; i++)
2276 tcp->u_arg[i] = tcp->status.pr_sysarg[i];
2277 }
John Hughes25299712001-03-06 10:10:06 +00002278#elif defined (I386)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002279 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002280 tcp->u_nargs = sysent[tcp->scno].nargs;
2281 else
2282 tcp->u_nargs = 5;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002283 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002284 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
John Hughes25299712001-03-06 10:10:06 +00002285#else
2286 I DONT KNOW WHAT TO DO
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002287#endif /* !HAVE_PR_SYSCALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002288#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002289#ifdef FREEBSD
2290 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2291 sysent[tcp->scno].nargs > tcp->status.val)
2292 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002293 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002294 tcp->u_nargs = tcp->status.val;
2295 if (tcp->u_nargs < 0)
2296 tcp->u_nargs = 0;
2297 if (tcp->u_nargs > MAX_ARGS)
2298 tcp->u_nargs = MAX_ARGS;
2299 switch(regs.r_eax) {
2300 case SYS___syscall:
2301 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2302 regs.r_esp + sizeof(int) + sizeof(quad_t));
2303 break;
2304 case SYS_syscall:
2305 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2306 regs.r_esp + 2 * sizeof(int));
2307 break;
2308 default:
2309 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2310 regs.r_esp + sizeof(int));
2311 break;
2312 }
2313#endif /* FREEBSD */
Pavel Machek4dc3b142000-02-01 17:58:41 +00002314 return 1;
2315}
2316
2317int
Dmitry V. Levin7d61ff12006-12-21 21:15:04 +00002318trace_syscall(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002319{
2320 int sys_res;
2321 struct timeval tv;
2322 int res;
2323
2324 /* Measure the exit time as early as possible to avoid errors. */
2325 if (dtime && (tcp->flags & TCB_INSYSCALL))
2326 gettimeofday(&tv, NULL);
2327
2328 res = get_scno(tcp);
2329 if (res != 1)
2330 return res;
2331
2332 res = syscall_fixup(tcp);
2333 if (res != 1)
2334 return res;
2335
2336 if (tcp->flags & TCB_INSYSCALL) {
2337 long u_error;
2338 res = get_error(tcp);
2339 if (res != 1)
2340 return res;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002341
2342 internal_syscall(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002343 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2344 !(qual_flags[tcp->scno] & QUAL_TRACE)) {
Pavel Machek4dc3b142000-02-01 17:58:41 +00002345 tcp->flags &= ~TCB_INSYSCALL;
2346 return 0;
2347 }
2348
2349 if (tcp->flags & TCB_REPRINT) {
2350 printleader(tcp);
2351 tprintf("<... ");
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002352 if (tcp->scno >= nsyscalls || tcp->scno < 0)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002353 tprintf("syscall_%lu", tcp->scno);
2354 else
2355 tprintf("%s", sysent[tcp->scno].sys_name);
2356 tprintf(" resumed> ");
2357 }
2358
Dmitry V. Levin7d61ff12006-12-21 21:15:04 +00002359 if (cflag)
2360 return count_syscall(tcp, &tv);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002361
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002362 if (tcp->scno >= nsyscalls || tcp->scno < 0
Pavel Machek4dc3b142000-02-01 17:58:41 +00002363 || (qual_flags[tcp->scno] & QUAL_RAW))
2364 sys_res = printargs(tcp);
Michal Ludvig17f8fb32002-11-06 13:17:21 +00002365 else {
2366 if (not_failing_only && tcp->u_error)
Roland McGrath761b5d72002-12-15 23:58:31 +00002367 return 0; /* ignore failed syscalls */
Pavel Machek4dc3b142000-02-01 17:58:41 +00002368 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
Roland McGrath761b5d72002-12-15 23:58:31 +00002369 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002370 u_error = tcp->u_error;
2371 tprintf(") ");
2372 tabto(acolumn);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002373 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2374 qual_flags[tcp->scno] & QUAL_RAW) {
Pavel Machek4dc3b142000-02-01 17:58:41 +00002375 if (u_error)
2376 tprintf("= -1 (errno %ld)", u_error);
2377 else
2378 tprintf("= %#lx", tcp->u_rval);
2379 }
2380 else if (!(sys_res & RVAL_NONE) && u_error) {
2381 switch (u_error) {
2382#ifdef LINUX
2383 case ERESTARTSYS:
2384 tprintf("= ? ERESTARTSYS (To be restarted)");
2385 break;
2386 case ERESTARTNOINTR:
2387 tprintf("= ? ERESTARTNOINTR (To be restarted)");
2388 break;
2389 case ERESTARTNOHAND:
2390 tprintf("= ? ERESTARTNOHAND (To be restarted)");
2391 break;
Roland McGrath9c555e72003-07-09 09:47:59 +00002392 case ERESTART_RESTARTBLOCK:
2393 tprintf("= ? ERESTART_RESTARTBLOCK (To be restarted)");
2394 break;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002395#endif /* LINUX */
2396 default:
2397 tprintf("= -1 ");
Wichert Akkerman4527dae2002-03-31 19:03:29 +00002398 if (u_error < 0)
2399 tprintf("E??? (errno %ld)", u_error);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002400 else if (u_error < nerrnos)
Roland McGrath761b5d72002-12-15 23:58:31 +00002401 tprintf("%s (%s)", errnoent[u_error],
2402 strerror(u_error));
Pavel Machek4dc3b142000-02-01 17:58:41 +00002403 else
Roland McGrath761b5d72002-12-15 23:58:31 +00002404 tprintf("ERRNO_%ld (%s)", u_error,
2405 strerror(u_error));
Pavel Machek4dc3b142000-02-01 17:58:41 +00002406 break;
2407 }
Dmitry V. Levin21a75342008-09-03 01:22:18 +00002408 if ((sys_res & RVAL_STR) && tcp->auxstr)
2409 tprintf(" (%s)", tcp->auxstr);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002410 }
2411 else {
2412 if (sys_res & RVAL_NONE)
2413 tprintf("= ?");
2414 else {
2415 switch (sys_res & RVAL_MASK) {
2416 case RVAL_HEX:
2417 tprintf("= %#lx", tcp->u_rval);
2418 break;
2419 case RVAL_OCTAL:
2420 tprintf("= %#lo", tcp->u_rval);
2421 break;
2422 case RVAL_UDECIMAL:
2423 tprintf("= %lu", tcp->u_rval);
2424 break;
2425 case RVAL_DECIMAL:
2426 tprintf("= %ld", tcp->u_rval);
2427 break;
Wichert Akkerman16a03d22000-08-10 02:14:04 +00002428#ifdef HAVE_LONG_LONG
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002429 case RVAL_LHEX:
2430 tprintf("= %#llx", tcp->u_lrval);
Wichert Akkerman16a03d22000-08-10 02:14:04 +00002431 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002432 case RVAL_LOCTAL:
2433 tprintf("= %#llo", tcp->u_lrval);
2434 break;
2435 case RVAL_LUDECIMAL:
2436 tprintf("= %llu", tcp->u_lrval);
2437 break;
2438 case RVAL_LDECIMAL:
2439 tprintf("= %lld", tcp->u_lrval);
2440 break;
Wichert Akkerman16a03d22000-08-10 02:14:04 +00002441#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00002442 default:
2443 fprintf(stderr,
2444 "invalid rval format\n");
2445 break;
2446 }
2447 }
2448 if ((sys_res & RVAL_STR) && tcp->auxstr)
2449 tprintf(" (%s)", tcp->auxstr);
2450 }
2451 if (dtime) {
2452 tv_sub(&tv, &tv, &tcp->etime);
2453 tprintf(" <%ld.%06ld>",
2454 (long) tv.tv_sec, (long) tv.tv_usec);
2455 }
2456 printtrailer(tcp);
2457
2458 dumpio(tcp);
2459 if (fflush(tcp->outf) == EOF)
2460 return -1;
2461 tcp->flags &= ~TCB_INSYSCALL;
2462 return 0;
2463 }
2464
2465 /* Entering system call */
2466 res = syscall_enter(tcp);
2467 if (res != 1)
2468 return res;
2469
Roland McGrath17352792005-06-07 23:21:26 +00002470 switch (known_scno(tcp)) {
Roland McGrathd5bd7e62008-08-25 03:16:26 +00002471#ifdef SYS_socket_subcall
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002472 case SYS_socketcall:
2473 decode_subcall(tcp, SYS_socket_subcall,
2474 SYS_socket_nsubcalls, deref_style);
2475 break;
Roland McGrathd5bd7e62008-08-25 03:16:26 +00002476#endif
2477#ifdef SYS_ipc_subcall
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002478 case SYS_ipc:
2479 decode_subcall(tcp, SYS_ipc_subcall,
2480 SYS_ipc_nsubcalls, shift_style);
2481 break;
Roland McGrathd5bd7e62008-08-25 03:16:26 +00002482#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002483#ifdef SVR4
2484#ifdef SYS_pgrpsys_subcall
2485 case SYS_pgrpsys:
2486 decode_subcall(tcp, SYS_pgrpsys_subcall,
2487 SYS_pgrpsys_nsubcalls, shift_style);
2488 break;
2489#endif /* SYS_pgrpsys_subcall */
2490#ifdef SYS_sigcall_subcall
2491 case SYS_sigcall:
2492 decode_subcall(tcp, SYS_sigcall_subcall,
2493 SYS_sigcall_nsubcalls, mask_style);
2494 break;
2495#endif /* SYS_sigcall_subcall */
2496 case SYS_msgsys:
2497 decode_subcall(tcp, SYS_msgsys_subcall,
2498 SYS_msgsys_nsubcalls, shift_style);
2499 break;
2500 case SYS_shmsys:
2501 decode_subcall(tcp, SYS_shmsys_subcall,
2502 SYS_shmsys_nsubcalls, shift_style);
2503 break;
2504 case SYS_semsys:
2505 decode_subcall(tcp, SYS_semsys_subcall,
2506 SYS_semsys_nsubcalls, shift_style);
2507 break;
2508#if 0 /* broken */
2509 case SYS_utssys:
2510 decode_subcall(tcp, SYS_utssys_subcall,
2511 SYS_utssys_nsubcalls, shift_style);
2512 break;
2513#endif
2514 case SYS_sysfs:
2515 decode_subcall(tcp, SYS_sysfs_subcall,
2516 SYS_sysfs_nsubcalls, shift_style);
2517 break;
2518 case SYS_spcall:
2519 decode_subcall(tcp, SYS_spcall_subcall,
2520 SYS_spcall_nsubcalls, shift_style);
2521 break;
2522#ifdef SYS_context_subcall
2523 case SYS_context:
2524 decode_subcall(tcp, SYS_context_subcall,
2525 SYS_context_nsubcalls, shift_style);
2526 break;
2527#endif /* SYS_context_subcall */
Wichert Akkerman8829a551999-06-11 13:18:40 +00002528#ifdef SYS_door_subcall
2529 case SYS_door:
2530 decode_subcall(tcp, SYS_door_subcall,
2531 SYS_door_nsubcalls, door_style);
2532 break;
2533#endif /* SYS_door_subcall */
John Hughesbdf48f52001-03-06 15:08:09 +00002534#ifdef SYS_kaio_subcall
2535 case SYS_kaio:
2536 decode_subcall(tcp, SYS_kaio_subcall,
2537 SYS_kaio_nsubcalls, shift_style);
2538 break;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002539#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002540#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002541#ifdef FREEBSD
2542 case SYS_msgsys:
2543 case SYS_shmsys:
2544 case SYS_semsys:
2545 decode_subcall(tcp, 0, 0, table_style);
2546 break;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002547#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002548#ifdef SUNOS4
2549 case SYS_semsys:
2550 decode_subcall(tcp, SYS_semsys_subcall,
2551 SYS_semsys_nsubcalls, shift_style);
2552 break;
2553 case SYS_msgsys:
2554 decode_subcall(tcp, SYS_msgsys_subcall,
2555 SYS_msgsys_nsubcalls, shift_style);
2556 break;
2557 case SYS_shmsys:
2558 decode_subcall(tcp, SYS_shmsys_subcall,
2559 SYS_shmsys_nsubcalls, shift_style);
2560 break;
2561#endif
2562 }
2563
2564 internal_syscall(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002565 if (tcp->scno >=0 && tcp->scno < nsyscalls && !(qual_flags[tcp->scno] & QUAL_TRACE)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002566 tcp->flags |= TCB_INSYSCALL;
2567 return 0;
2568 }
2569
2570 if (cflag) {
2571 gettimeofday(&tcp->etime, NULL);
2572 tcp->flags |= TCB_INSYSCALL;
2573 return 0;
2574 }
2575
2576 printleader(tcp);
2577 tcp->flags &= ~TCB_REPRINT;
2578 tcp_last = tcp;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002579 if (tcp->scno >= nsyscalls || tcp->scno < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002580 tprintf("syscall_%lu(", tcp->scno);
2581 else
2582 tprintf("%s(", sysent[tcp->scno].sys_name);
Roland McGrath761b5d72002-12-15 23:58:31 +00002583 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002584 ((qual_flags[tcp->scno] & QUAL_RAW) && tcp->scno != SYS_exit))
2585 sys_res = printargs(tcp);
2586 else
2587 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2588 if (fflush(tcp->outf) == EOF)
2589 return -1;
2590 tcp->flags |= TCB_INSYSCALL;
2591 /* Measure the entrance time as late as possible to avoid errors. */
2592 if (dtime)
2593 gettimeofday(&tcp->etime, NULL);
2594 return sys_res;
2595}
2596
2597int
2598printargs(tcp)
2599struct tcb *tcp;
2600{
2601 if (entering(tcp)) {
2602 int i;
2603
2604 for (i = 0; i < tcp->u_nargs; i++)
2605 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
2606 }
2607 return 0;
2608}
2609
2610long
2611getrval2(tcp)
2612struct tcb *tcp;
2613{
2614 long val = -1;
2615
2616#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002617#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002618 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002619 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
2620 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002621 val = regs.r_o1;
Roland McGrath6b1d43e2003-03-31 01:05:01 +00002622#elif defined(SH)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002623 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
Roland McGrath6b1d43e2003-03-31 01:05:01 +00002624 return -1;
Roland McGrathb4ce1762004-03-01 20:30:48 +00002625#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002626 if (upeek(tcp, PT_R9, &val) < 0)
Roland McGrathb4ce1762004-03-01 20:30:48 +00002627 return -1;
Roland McGrath920e6bb2005-03-15 02:15:20 +00002628#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002629#endif /* LINUX */
2630
2631#ifdef SUNOS4
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002632 if (upeek(tcp, uoff(u_rval2), &val) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002633 return -1;
2634#endif /* SUNOS4 */
2635
2636#ifdef SVR4
2637#ifdef SPARC
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002638 val = tcp->status.PR_REG[R_O1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002639#endif /* SPARC */
2640#ifdef I386
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002641 val = tcp->status.PR_REG[EDX];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002642#endif /* I386 */
Michal Ludvig0e035502002-09-23 15:41:01 +00002643#ifdef X86_64
2644 val = tcp->status.PR_REG[RDX];
2645#endif /* X86_64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002646#ifdef MIPS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002647 val = tcp->status.PR_REG[CTX_V1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002648#endif /* MIPS */
2649#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002650#ifdef FREEBSD
2651 struct reg regs;
2652 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
2653 val = regs.r_edx;
Roland McGrath761b5d72002-12-15 23:58:31 +00002654#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002655 return val;
2656}
2657
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +00002658#ifdef SUNOS4
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002659/*
2660 * Apparently, indirect system calls have already be converted by ptrace(2),
2661 * so if you see "indir" this program has gone astray.
2662 */
2663int
2664sys_indir(tcp)
2665struct tcb *tcp;
2666{
2667 int i, scno, nargs;
2668
2669 if (entering(tcp)) {
2670 if ((scno = tcp->u_arg[0]) > nsyscalls) {
2671 fprintf(stderr, "Bogus syscall: %u\n", scno);
2672 return 0;
2673 }
2674 nargs = sysent[scno].nargs;
2675 tprintf("%s", sysent[scno].sys_name);
2676 for (i = 0; i < nargs; i++)
2677 tprintf(", %#lx", tcp->u_arg[i+1]);
2678 }
2679 return 0;
2680}
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +00002681#endif /* SUNOS4 */
Dmitry V. Levin2e55ff42008-09-03 01:02:46 +00002682
2683int
2684is_restart_error(struct tcb *tcp)
2685{
2686#ifdef LINUX
2687 if (!syserror(tcp))
2688 return 0;
2689 switch (tcp->u_error) {
2690 case ERESTARTSYS:
2691 case ERESTARTNOINTR:
2692 case ERESTARTNOHAND:
2693 case ERESTART_RESTARTBLOCK:
2694 return 1;
2695 default:
2696 break;
2697 }
2698#endif /* LINUX */
2699 return 0;
2700}