blob: ba176458e0193766b3e3e3b374e2ea40c8f7837c [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 const int socket_map [] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000588 /* SYS_SOCKET */ 97,
589 /* SYS_BIND */ 104,
590 /* SYS_CONNECT */ 98,
591 /* SYS_LISTEN */ 106,
592 /* SYS_ACCEPT */ 99,
593 /* SYS_GETSOCKNAME */ 150,
594 /* SYS_GETPEERNAME */ 141,
595 /* SYS_SOCKETPAIR */ 135,
596 /* SYS_SEND */ 101,
597 /* SYS_RECV */ 102,
598 /* SYS_SENDTO */ 133,
599 /* SYS_RECVFROM */ 125,
600 /* SYS_SHUTDOWN */ 134,
601 /* SYS_SETSOCKOPT */ 105,
602 /* SYS_GETSOCKOPT */ 118,
603 /* SYS_SENDMSG */ 114,
604 /* SYS_RECVMSG */ 113
605};
606
Roland McGratha4d48532005-06-08 20:45:28 +0000607#if defined (SPARC) || defined (SPARC64)
608static void
Wichert Akkermane6f876c1999-06-22 15:28:30 +0000609sparc_socket_decode (tcp)
610struct tcb *tcp;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000611{
612 volatile long addr;
613 volatile int i, n;
614
615 if (tcp->u_arg [0] < 1 || tcp->u_arg [0] > sizeof(socket_map)/sizeof(int)+1){
616 return;
617 }
618 tcp->scno = socket_map [tcp->u_arg [0]-1];
619 n = tcp->u_nargs = sysent [tcp->scno].nargs;
620 addr = tcp->u_arg [1];
621 for (i = 0; i < n; i++){
622 int arg;
623 if (umoven (tcp, addr, sizeof (arg), (void *) &arg) < 0)
624 arg = 0;
625 tcp->u_arg [i] = arg;
626 addr += sizeof (arg);
627 }
628}
Roland McGratha4d48532005-06-08 20:45:28 +0000629#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000630
Roland McGratha4d48532005-06-08 20:45:28 +0000631static void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000632decode_subcall(tcp, subcall, nsubcalls, style)
633struct tcb *tcp;
634int subcall;
635int nsubcalls;
636enum subcall_style style;
637{
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000638 unsigned long addr, mask;
Michal Ludvig10a88d02002-10-07 14:31:00 +0000639 int i;
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000640 int size = personality_wordsize[current_personality];
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000641
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000642 switch (style) {
643 case shift_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000644 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
645 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000646 tcp->scno = subcall + tcp->u_arg[0];
647 if (sysent[tcp->scno].nargs != -1)
648 tcp->u_nargs = sysent[tcp->scno].nargs;
649 else
650 tcp->u_nargs--;
651 for (i = 0; i < tcp->u_nargs; i++)
652 tcp->u_arg[i] = tcp->u_arg[i + 1];
653 break;
654 case deref_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000655 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
656 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000657 tcp->scno = subcall + tcp->u_arg[0];
658 addr = tcp->u_arg[1];
659 for (i = 0; i < sysent[tcp->scno].nargs; i++) {
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000660 if (size == sizeof(int)) {
661 unsigned int arg;
662 if (umove(tcp, addr, &arg) < 0)
663 arg = 0;
664 tcp->u_arg[i] = arg;
665 }
666 else if (size == sizeof(long)) {
667 unsigned long arg;
668 if (umove(tcp, addr, &arg) < 0)
669 arg = 0;
670 tcp->u_arg[i] = arg;
671 }
672 else
673 abort();
674 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000675 }
676 tcp->u_nargs = sysent[tcp->scno].nargs;
677 break;
678 case mask_style:
679 mask = (tcp->u_arg[0] >> 8) & 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000680 for (i = 0; mask; i++)
681 mask >>= 1;
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000682 if (i >= nsubcalls)
683 return;
684 tcp->u_arg[0] &= 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000685 tcp->scno = subcall + i;
686 if (sysent[tcp->scno].nargs != -1)
687 tcp->u_nargs = sysent[tcp->scno].nargs;
688 break;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000689 case door_style:
690 /*
691 * Oh, yuck. The call code is the *sixth* argument.
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000692 * (don't you mean the *last* argument? - JH)
Wichert Akkerman8829a551999-06-11 13:18:40 +0000693 */
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000694 if (tcp->u_arg[5] < 0 || tcp->u_arg[5] >= nsubcalls)
695 return;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000696 tcp->scno = subcall + tcp->u_arg[5];
697 if (sysent[tcp->scno].nargs != -1)
698 tcp->u_nargs = sysent[tcp->scno].nargs;
699 else
700 tcp->u_nargs--;
701 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000702#ifdef FREEBSD
703 case table_style:
704 for (i = 0; i < sizeof(subcalls_table) / sizeof(struct subcall); i++)
705 if (subcalls_table[i].call == tcp->scno) break;
706 if (i < sizeof(subcalls_table) / sizeof(struct subcall) &&
707 tcp->u_arg[0] >= 0 && tcp->u_arg[0] < subcalls_table[i].nsubcalls) {
708 tcp->scno = subcalls_table[i].subcalls[tcp->u_arg[0]];
709 for (i = 0; i < tcp->u_nargs; i++)
710 tcp->u_arg[i] = tcp->u_arg[i + 1];
711 }
712 break;
713#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000714 }
715}
716#endif
717
718struct tcb *tcp_last = NULL;
719
720static int
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000721internal_syscall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000722{
723 /*
724 * We must always trace a few critical system calls in order to
725 * correctly support following forks in the presence of tracing
726 * qualifiers.
727 */
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000728 int (*func)();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000729
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000730 if (tcp->scno < 0 || tcp->scno >= nsyscalls)
731 return 0;
732
733 func = sysent[tcp->scno].sys_func;
734
735 if (sys_exit == func)
736 return internal_exit(tcp);
737
738 if ( sys_fork == func
739#if defined(FREEBSD) || defined(LINUX) || defined(SUNOS4)
740 || sys_vfork == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000741#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000742#if UNIXWARE > 2
743 || sys_rfork == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000744#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000745 )
746 return internal_fork(tcp);
747
748#if defined(LINUX) && (defined SYS_clone || defined SYS_clone2)
749 if (sys_clone == func)
750 return internal_clone(tcp);
Roland McGrathc74c0b72004-09-01 19:39:46 +0000751#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000752
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000753 if ( sys_execve == func
754#if defined(SPARC) || defined(SPARC64) || defined(SUNOS4)
755 || sys_execv == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000756#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000757#if UNIXWARE > 2
758 || sys_rexecve == func
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000759#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000760 )
761 return internal_exec(tcp);
762
763 if ( sys_waitpid == func
764 || sys_wait4 == func
765#if defined(SVR4) || defined(FREEBSD) || defined(SUNOS4)
766 || sys_wait == func
Roland McGrath923f7502003-01-09 06:53:27 +0000767#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000768#ifdef ALPHA
769 || sys_osf_wait4 == func
Roland McGrath08267b82004-02-20 22:56:43 +0000770#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000771 )
772 return internal_wait(tcp, 2);
773
774#if defined(LINUX) || defined(SVR4)
775 if (sys_waitid == func)
776 return internal_wait(tcp, 3);
777#endif
778
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000779 return 0;
780}
781
Wichert Akkermanc7926982000-04-10 22:22:31 +0000782
783#ifdef LINUX
784#if defined (I386)
785 static long eax;
786#elif defined (IA64)
787 long r8, r10, psr;
788 long ia32 = 0;
789#elif defined (POWERPC)
790 static long result,flags;
791#elif defined (M68K)
792 static int d0;
793#elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +0000794 static struct pt_regs regs;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000795#elif defined (ALPHA)
796 static long r0;
797 static long a3;
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000798#elif defined (SPARC) || defined (SPARC64)
Wichert Akkerman00a82ee2001-03-28 20:29:17 +0000799 static struct regs regs;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000800 static unsigned long trap;
801#elif defined(MIPS)
802 static long a3;
803 static long r2;
Michal Ludvig10a88d02002-10-07 14:31:00 +0000804#elif defined(S390) || defined(S390X)
Wichert Akkermanc7926982000-04-10 22:22:31 +0000805 static long gpr2;
806 static long pc;
Michal Ludvig882eda82002-11-11 12:50:47 +0000807 static long syscall_mode;
Wichert Akkermanc1652e22001-03-27 12:17:16 +0000808#elif defined(HPPA)
809 static long r28;
Wichert Akkermanccef6372002-05-01 16:39:22 +0000810#elif defined(SH)
811 static long r0;
Roland McGrathf5a47772003-06-26 22:40:42 +0000812#elif defined(SH64)
Roland McGrath0f87c492003-06-03 23:29:04 +0000813 static long r9;
Michal Ludvig0e035502002-09-23 15:41:01 +0000814#elif defined(X86_64)
815 static long rax;
Roland McGrath761b5d72002-12-15 23:58:31 +0000816#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000817#endif /* LINUX */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000818#ifdef FREEBSD
819 struct reg regs;
Roland McGrath761b5d72002-12-15 23:58:31 +0000820#endif /* FREEBSD */
Wichert Akkermanc7926982000-04-10 22:22:31 +0000821
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000822int
Pavel Machek4dc3b142000-02-01 17:58:41 +0000823get_scno(tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000824struct tcb *tcp;
825{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000826 long scno = 0;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000827#ifndef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000828 int pid = tcp->pid;
Roland McGrath761b5d72002-12-15 23:58:31 +0000829#endif /* !PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000830
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000831#ifdef LINUX
Michal Ludvig10a88d02002-10-07 14:31:00 +0000832#if defined(S390) || defined(S390X)
Roland McGrath96dc5142003-01-20 10:23:04 +0000833 if (tcp->flags & TCB_WAITEXECVE) {
834 /*
835 * When the execve system call completes successfully, the
836 * new process still has -ENOSYS (old style) or __NR_execve
837 * (new style) in gpr2. We cannot recover the scno again
838 * by disassembly, because the image that executed the
839 * syscall is gone now. Fortunately, we don't want it. We
840 * leave the flag set so that syscall_fixup can fake the
841 * result.
842 */
843 if (tcp->flags & TCB_INSYSCALL)
844 return 1;
845 /*
846 * This is the SIGTRAP after execve. We cannot try to read
847 * the system call here either.
848 */
849 tcp->flags &= ~TCB_WAITEXECVE;
850 return 0;
851 }
Roland McGrath2f924ca2003-06-26 22:23:28 +0000852
853 if (upeek(pid, PT_GPR2, &syscall_mode) < 0)
854 return -1;
855
856 if (syscall_mode != -ENOSYS) {
857 /*
858 * Since kernel version 2.5.44 the scno gets passed in gpr2.
859 */
860 scno = syscall_mode;
861 } else {
Michal Ludvig882eda82002-11-11 12:50:47 +0000862 /*
863 * Old style of "passing" the scno via the SVC instruction.
864 */
865
866 long opcode, offset_reg, tmp;
867 void * svc_addr;
868 int gpr_offset[16] = {PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
869 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
870 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
871 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15};
Roland McGrath761b5d72002-12-15 23:58:31 +0000872
Michal Ludvig882eda82002-11-11 12:50:47 +0000873 if (upeek(pid, PT_PSWADDR, &pc) < 0)
874 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000875 errno = 0;
Michal Ludvig882eda82002-11-11 12:50:47 +0000876 opcode = ptrace(PTRACE_PEEKTEXT, pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000877 if (errno) {
878 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000879 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000880 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000881
882 /*
883 * We have to check if the SVC got executed directly or via an
884 * EXECUTE instruction. In case of EXECUTE it is necessary to do
885 * instruction decoding to derive the system call number.
886 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
887 * so that this doesn't work if a SVC opcode is part of an EXECUTE
888 * opcode. Since there is no way to find out the opcode size this
889 * is the best we can do...
890 */
891
892 if ((opcode & 0xff00) == 0x0a00) {
893 /* SVC opcode */
894 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000895 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000896 else {
897 /* SVC got executed by EXECUTE instruction */
898
899 /*
900 * Do instruction decoding of EXECUTE. If you really want to
901 * understand this, read the Principles of Operations.
902 */
903 svc_addr = (void *) (opcode & 0xfff);
904
905 tmp = 0;
906 offset_reg = (opcode & 0x000f0000) >> 16;
907 if (offset_reg && (upeek(pid, gpr_offset[offset_reg], &tmp) < 0))
908 return -1;
909 svc_addr += tmp;
910
911 tmp = 0;
912 offset_reg = (opcode & 0x0000f000) >> 12;
913 if (offset_reg && (upeek(pid, gpr_offset[offset_reg], &tmp) < 0))
914 return -1;
915 svc_addr += tmp;
916
917 scno = ptrace(PTRACE_PEEKTEXT, pid, svc_addr, 0);
918 if (errno)
919 return -1;
920#if defined(S390X)
921 scno >>= 48;
922#else
923 scno >>= 16;
924#endif
925 tmp = 0;
926 offset_reg = (opcode & 0x00f00000) >> 20;
927 if (offset_reg && (upeek(pid, gpr_offset[offset_reg], &tmp) < 0))
928 return -1;
929
930 scno = (scno | tmp) & 0xff;
931 }
932 }
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +0000933#elif defined (POWERPC)
Roland McGratheb285352003-01-14 09:59:00 +0000934 if (upeek(pid, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000935 return -1;
936 if (!(tcp->flags & TCB_INSYSCALL)) {
937 /* Check if we return from execve. */
938 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
939 tcp->flags &= ~TCB_WAITEXECVE;
940 return 0;
941 }
942 }
943#elif defined (I386)
944 if (upeek(pid, 4*ORIG_EAX, &scno) < 0)
945 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +0000946#elif defined (X86_64)
947 if (upeek(pid, 8*ORIG_RAX, &scno) < 0)
948 return -1;
949
Roland McGrath761b5d72002-12-15 23:58:31 +0000950 if (!(tcp->flags & TCB_INSYSCALL)) {
951 static int currpers=-1;
Michal Ludvig0e035502002-09-23 15:41:01 +0000952 long val;
953
954 /* Check CS register value. On x86-64 linux it is:
955 * 0x33 for long mode (64 bit)
956 * 0x23 for compatibility mode (32 bit)
Roland McGrath761b5d72002-12-15 23:58:31 +0000957 * It takes only one ptrace and thus doesn't need
Michal Ludvig0e035502002-09-23 15:41:01 +0000958 * to be cached.
959 */
960 if (upeek(pid, 8*CS, &val) < 0)
961 return -1;
962 switch(val)
963 {
964 case 0x23: currpers = 1; break;
965 case 0x33: currpers = 0; break;
966 default:
967 fprintf(stderr, "Unknown value CS=0x%02X while "
968 "detecting personality of process "
969 "PID=%d\n", (int)val, pid);
970 currpers = current_personality;
971 break;
972 }
973#if 0
974 /* This version analyzes the opcode of a syscall instruction.
975 * (int 0x80 on i386 vs. syscall on x86-64)
976 * It works, but is too complicated.
977 */
978 unsigned long val, rip, i;
979
980 if(upeek(pid, 8*RIP, &rip)<0)
981 perror("upeek(RIP)");
Roland McGrath761b5d72002-12-15 23:58:31 +0000982
Michal Ludvig0e035502002-09-23 15:41:01 +0000983 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
984 rip-=2;
985 errno = 0;
986
Roland McGrath761b5d72002-12-15 23:58:31 +0000987 call = ptrace(PTRACE_PEEKTEXT,pid,(char *)rip,0);
988 if (errno)
989 printf("ptrace_peektext failed: %s\n",
Michal Ludvig0e035502002-09-23 15:41:01 +0000990 strerror(errno));
991 switch (call & 0xffff)
992 {
993 /* x86-64: syscall = 0x0f 0x05 */
994 case 0x050f: currpers = 0; break;
995 /* i386: int 0x80 = 0xcd 0x80 */
996 case 0x80cd: currpers = 1; break;
997 default:
998 currpers = current_personality;
Roland McGrath761b5d72002-12-15 23:58:31 +0000999 fprintf(stderr,
Michal Ludvig0e035502002-09-23 15:41:01 +00001000 "Unknown syscall opcode (0x%04X) while "
1001 "detecting personality of process "
1002 "PID=%d\n", (int)call, pid);
1003 break;
1004 }
1005#endif
1006 if(currpers != current_personality)
1007 {
1008 char *names[]={"64 bit", "32 bit"};
1009 set_personality(currpers);
Roland McGrath761b5d72002-12-15 23:58:31 +00001010 printf("[ Process PID=%d runs in %s mode. ]\n",
Michal Ludvig0e035502002-09-23 15:41:01 +00001011 pid, names[current_personality]);
1012 }
Roland McGrath761b5d72002-12-15 23:58:31 +00001013 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001014#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001015# define IA64_PSR_IS ((long)1 << 34)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001016 if (upeek (pid, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001017 ia32 = (psr & IA64_PSR_IS) != 0;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001018 if (!(tcp->flags & TCB_INSYSCALL)) {
1019 if (ia32) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001020 if (upeek(pid, PT_R1, &scno) < 0) /* orig eax */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001021 return -1;
1022 } else {
1023 if (upeek (pid, PT_R15, &scno) < 0)
1024 return -1;
1025 }
Roland McGrathba954762003-03-05 06:29:06 +00001026 /* Check if we return from execve. */
1027 if (tcp->flags & TCB_WAITEXECVE) {
1028 tcp->flags &= ~TCB_WAITEXECVE;
1029 return 0;
1030 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001031 } else {
1032 /* syscall in progress */
1033 if (upeek (pid, PT_R8, &r8) < 0)
1034 return -1;
1035 if (upeek (pid, PT_R10, &r10) < 0)
1036 return -1;
1037 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001038#elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001039 /*
1040 * Read complete register set in one go.
1041 */
1042 if (ptrace(PTRACE_GETREGS, pid, NULL, (void *)&regs) == -1)
1043 return -1;
1044
1045 /*
1046 * We only need to grab the syscall number on syscall entry.
1047 */
1048 if (regs.ARM_ip == 0) {
Roland McGrath9bc63402007-11-01 21:42:18 +00001049 if (!(tcp->flags & TCB_INSYSCALL)) {
1050 /* Check if we return from execve. */
1051 if (tcp->flags & TCB_WAITEXECVE) {
1052 tcp->flags &= ~TCB_WAITEXECVE;
1053 return 0;
1054 }
1055 }
1056
Roland McGrath0f87c492003-06-03 23:29:04 +00001057 /*
1058 * Note: we only deal with only 32-bit CPUs here.
1059 */
1060 if (regs.ARM_cpsr & 0x20) {
1061 /*
1062 * Get the Thumb-mode system call number
1063 */
1064 scno = regs.ARM_r7;
1065 } else {
1066 /*
1067 * Get the ARM-mode system call number
1068 */
1069 errno = 0;
1070 scno = ptrace(PTRACE_PEEKTEXT, pid, (void *)(regs.ARM_pc - 4), NULL);
1071 if (errno)
1072 return -1;
1073
1074 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
1075 tcp->flags &= ~TCB_WAITEXECVE;
1076 return 0;
1077 }
1078
Roland McGrathf691bd22006-04-25 07:34:41 +00001079 /* Handle the EABI syscall convention. We do not
1080 bother converting structures between the two
1081 ABIs, but basic functionality should work even
1082 if strace and the traced program have different
1083 ABIs. */
1084 if (scno == 0xef000000) {
1085 scno = regs.ARM_r7;
1086 } else {
1087 if ((scno & 0x0ff00000) != 0x0f900000) {
1088 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1089 scno);
1090 return -1;
1091 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001092
Roland McGrathf691bd22006-04-25 07:34:41 +00001093 /*
1094 * Fixup the syscall number
1095 */
1096 scno &= 0x000fffff;
1097 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001098 }
1099
1100 if (tcp->flags & TCB_INSYSCALL) {
1101 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1102 tcp->flags &= ~TCB_INSYSCALL;
1103 }
1104 } else {
1105 if (!(tcp->flags & TCB_INSYSCALL)) {
1106 fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
1107 tcp->flags |= TCB_INSYSCALL;
1108 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001109 }
1110#elif defined (M68K)
1111 if (upeek(pid, 4*PT_ORIG_D0, &scno) < 0)
1112 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001113#elif defined (MIPS)
1114 if (upeek(pid, REG_A3, &a3) < 0)
1115 return -1;
1116
1117 if(!(tcp->flags & TCB_INSYSCALL)) {
1118 if (upeek(pid, REG_V0, &scno) < 0)
1119 return -1;
1120
1121 if (scno < 0 || scno > nsyscalls) {
1122 if(a3 == 0 || a3 == -1) {
1123 if(debug)
1124 fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
1125 return 0;
1126 }
1127 }
1128 } else {
1129 if (upeek(pid, REG_V0, &r2) < 0)
1130 return -1;
1131 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001132#elif defined (ALPHA)
1133 if (upeek(pid, REG_A3, &a3) < 0)
1134 return -1;
1135
1136 if (!(tcp->flags & TCB_INSYSCALL)) {
1137 if (upeek(pid, REG_R0, &scno) < 0)
1138 return -1;
1139
1140 /* Check if we return from execve. */
1141 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1142 tcp->flags &= ~TCB_WAITEXECVE;
1143 return 0;
1144 }
1145
1146 /*
1147 * Do some sanity checks to figure out if it's
1148 * really a syscall entry
1149 */
1150 if (scno < 0 || scno > nsyscalls) {
1151 if (a3 == 0 || a3 == -1) {
1152 if (debug)
1153 fprintf (stderr, "stray syscall exit: r0 = %ld\n", scno);
1154 return 0;
1155 }
1156 }
1157 }
1158 else {
1159 if (upeek(pid, REG_R0, &r0) < 0)
1160 return -1;
1161 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001162#elif defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163 /* Everything we need is in the current register set. */
1164 if (ptrace(PTRACE_GETREGS,pid,(char *)&regs,0) < 0)
1165 return -1;
1166
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001167 /* If we are entering, then disassemble the syscall trap. */
1168 if (!(tcp->flags & TCB_INSYSCALL)) {
1169 /* Retrieve the syscall trap instruction. */
1170 errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001171 trap = ptrace(PTRACE_PEEKTEXT,pid,(char *)regs.r_pc,0);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001172#if defined(SPARC64)
1173 trap >>= 32;
1174#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175 if (errno)
1176 return -1;
1177
1178 /* Disassemble the trap to see what personality to use. */
1179 switch (trap) {
1180 case 0x91d02010:
1181 /* Linux/SPARC syscall trap. */
1182 set_personality(0);
1183 break;
Wichert Akkermandacfb6e1999-06-03 14:21:07 +00001184 case 0x91d0206d:
1185 /* Linux/SPARC64 syscall trap. */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001186 set_personality(2);
1187 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001188 case 0x91d02000:
1189 /* SunOS syscall trap. (pers 1) */
1190 fprintf(stderr,"syscall: SunOS no support\n");
1191 return -1;
1192 case 0x91d02008:
1193 /* Solaris 2.x syscall trap. (per 2) */
1194 set_personality(1);
Roland McGrath761b5d72002-12-15 23:58:31 +00001195 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001196 case 0x91d02009:
1197 /* NetBSD/FreeBSD syscall trap. */
1198 fprintf(stderr,"syscall: NetBSD/FreeBSD not supported\n");
1199 return -1;
1200 case 0x91d02027:
1201 /* Solaris 2.x gettimeofday */
1202 set_personality(1);
1203 break;
1204 default:
1205 /* Unknown syscall trap. */
1206 if(tcp->flags & TCB_WAITEXECVE) {
1207 tcp->flags &= ~TCB_WAITEXECVE;
1208 return 0;
1209 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001210#if defined (SPARC64)
1211 fprintf(stderr,"syscall: unknown syscall trap %08lx %016lx\n", trap, regs.r_tpc);
1212#else
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001213 fprintf(stderr,"syscall: unknown syscall trap %08x %08x\n", trap, regs.r_pc);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001214#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001215 return -1;
1216 }
1217
1218 /* Extract the system call number from the registers. */
1219 if (trap == 0x91d02027)
1220 scno = 156;
1221 else
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001222 scno = regs.r_g1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001223 if (scno == 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001224 scno = regs.r_o0;
1225 memmove (&regs.r_o0, &regs.r_o1, 7*sizeof(regs.r_o0));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001226 }
1227 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001228#elif defined(HPPA)
1229 if (upeek(pid, PT_GR20, &scno) < 0)
1230 return -1;
1231 if (!(tcp->flags & TCB_INSYSCALL)) {
1232 /* Check if we return from execve. */
1233 if ((tcp->flags & TCB_WAITEXECVE)) {
1234 tcp->flags &= ~TCB_WAITEXECVE;
1235 return 0;
1236 }
1237 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00001238#elif defined(SH)
1239 /*
1240 * In the new syscall ABI, the system call number is in R3.
1241 */
1242 if (upeek(pid, 4*(REG_REG0+3), &scno) < 0)
1243 return -1;
1244
1245 if (scno < 0) {
1246 /* Odd as it may seem, a glibc bug has been known to cause
1247 glibc to issue bogus negative syscall numbers. So for
1248 our purposes, make strace print what it *should* have been */
1249 long correct_scno = (scno & 0xff);
1250 if (debug)
1251 fprintf(stderr,
Michal Ludvig53b320f2002-09-23 13:30:09 +00001252 "Detected glibc bug: bogus system call number = %ld, "
1253 "correcting to %ld\n",
Wichert Akkermanccef6372002-05-01 16:39:22 +00001254 scno,
1255 correct_scno);
1256 scno = correct_scno;
1257 }
1258
1259
1260 if (!(tcp->flags & TCB_INSYSCALL)) {
1261 /* Check if we return from execve. */
1262 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1263 tcp->flags &= ~TCB_WAITEXECVE;
1264 return 0;
1265 }
1266 }
Roland McGrathf5a47772003-06-26 22:40:42 +00001267#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001268 if (upeek(pid, REG_SYSCALL, &scno) < 0)
1269 return -1;
1270 scno &= 0xFFFF;
1271
1272 if (!(tcp->flags & TCB_INSYSCALL)) {
1273 /* Check if we return from execve. */
1274 if (tcp->flags & TCB_WAITEXECVE) {
1275 tcp->flags &= ~TCB_WAITEXECVE;
1276 return 0;
1277 }
1278 }
Roland McGrathf5a47772003-06-26 22:40:42 +00001279#endif /* SH64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001280#endif /* LINUX */
1281#ifdef SUNOS4
1282 if (upeek(pid, uoff(u_arg[7]), &scno) < 0)
1283 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001284#elif defined(SH)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001285 /* new syscall ABI returns result in R0 */
1286 if (upeek(pid, 4*REG_REG0, (long *)&r0) < 0)
1287 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001288#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001289 /* ABI defines result returned in r9 */
1290 if (upeek(pid, REG_GENERAL(9), (long *)&r9) < 0)
1291 return -1;
1292
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001293#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001294#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001295#ifdef HAVE_PR_SYSCALL
John Hughes25299712001-03-06 10:10:06 +00001296 scno = tcp->status.PR_SYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001297#else /* !HAVE_PR_SYSCALL */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001298#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001299 scno = tcp->status.PR_WHAT;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001300#else /* FREEBSD */
1301 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1302 perror("pread");
1303 return -1;
1304 }
1305 switch (regs.r_eax) {
1306 case SYS_syscall:
1307 case SYS___syscall:
1308 pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int));
1309 break;
1310 default:
1311 scno = regs.r_eax;
1312 break;
1313 }
1314#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001315#endif /* !HAVE_PR_SYSCALL */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001316#endif /* USE_PROCFS */
Wichert Akkerman5ae21ea2000-05-01 01:53:59 +00001317 if (!(tcp->flags & TCB_INSYSCALL))
1318 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001319 return 1;
1320}
1321
Pavel Machek4dc3b142000-02-01 17:58:41 +00001322
Roland McGrath17352792005-06-07 23:21:26 +00001323long
1324known_scno(tcp)
1325struct tcb *tcp;
1326{
1327 long scno = tcp->scno;
1328 if (scno >= 0 && scno < nsyscalls && sysent[scno].native_scno != 0)
1329 scno = sysent[scno].native_scno;
1330 else
1331 scno += NR_SYSCALL_BASE;
1332 return scno;
1333}
1334
Roland McGratha4d48532005-06-08 20:45:28 +00001335static int
Pavel Machek4dc3b142000-02-01 17:58:41 +00001336syscall_fixup(tcp)
1337struct tcb *tcp;
1338{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001339#ifndef USE_PROCFS
Pavel Machek4dc3b142000-02-01 17:58:41 +00001340 int pid = tcp->pid;
Roland McGrath761b5d72002-12-15 23:58:31 +00001341#else /* USE_PROCFS */
Roland McGrath17352792005-06-07 23:21:26 +00001342 int scno = known_scno(tcp);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001343
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001344 if (!(tcp->flags & TCB_INSYSCALL)) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001345 if (tcp->status.PR_WHY != PR_SYSENTRY) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001346 if (
1347 scno == SYS_fork
1348#ifdef SYS_vfork
1349 || scno == SYS_vfork
1350#endif /* SYS_vfork */
John Hughes4e36a812001-04-18 15:11:51 +00001351#ifdef SYS_fork1
1352 || scno == SYS_fork1
1353#endif /* SYS_fork1 */
1354#ifdef SYS_forkall
1355 || scno == SYS_forkall
1356#endif /* SYS_forkall */
1357#ifdef SYS_rfork1
1358 || scno == SYS_rfork1
1359#endif /* SYS_fork1 */
1360#ifdef SYS_rforkall
1361 || scno == SYS_rforkall
1362#endif /* SYS_rforkall */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001363 ) {
1364 /* We are returning in the child, fake it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001365 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001366 trace_syscall(tcp);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001367 tcp->status.PR_WHY = PR_SYSEXIT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001368 }
1369 else {
1370 fprintf(stderr, "syscall: missing entry\n");
1371 tcp->flags |= TCB_INSYSCALL;
1372 }
1373 }
1374 }
1375 else {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001376 if (tcp->status.PR_WHY != PR_SYSEXIT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001377 fprintf(stderr, "syscall: missing exit\n");
1378 tcp->flags &= ~TCB_INSYSCALL;
1379 }
1380 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001381#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001382#ifdef SUNOS4
1383 if (!(tcp->flags & TCB_INSYSCALL)) {
1384 if (scno == 0) {
1385 fprintf(stderr, "syscall: missing entry\n");
1386 tcp->flags |= TCB_INSYSCALL;
1387 }
1388 }
1389 else {
1390 if (scno != 0) {
1391 if (debug) {
1392 /*
1393 * This happens when a signal handler
1394 * for a signal which interrupted a
1395 * a system call makes another system call.
1396 */
1397 fprintf(stderr, "syscall: missing exit\n");
1398 }
1399 tcp->flags &= ~TCB_INSYSCALL;
1400 }
1401 }
1402#endif /* SUNOS4 */
1403#ifdef LINUX
1404#if defined (I386)
1405 if (upeek(pid, 4*EAX, &eax) < 0)
1406 return -1;
1407 if (eax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1408 if (debug)
1409 fprintf(stderr, "stray syscall exit: eax = %ld\n", eax);
1410 return 0;
1411 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001412#elif defined (X86_64)
1413 if (upeek(pid, 8*RAX, &rax) < 0)
1414 return -1;
Roland McGrath998fac72004-06-23 01:40:45 +00001415 if (current_personality == 1)
1416 rax = (long int)(int)rax; /* sign extend from 32 bits */
Michal Ludvig0e035502002-09-23 15:41:01 +00001417 if (rax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1418 if (debug)
1419 fprintf(stderr, "stray syscall exit: rax = %ld\n", rax);
1420 return 0;
1421 }
Michal Ludvig10a88d02002-10-07 14:31:00 +00001422#elif defined (S390) || defined (S390X)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001423 if (upeek(pid, PT_GPR2, &gpr2) < 0)
1424 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001425 if (syscall_mode != -ENOSYS)
1426 syscall_mode = tcp->scno;
1427 if (gpr2 != syscall_mode && !(tcp->flags & TCB_INSYSCALL)) {
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001428 if (debug)
1429 fprintf(stderr, "stray syscall exit: gpr2 = %ld\n", gpr2);
1430 return 0;
1431 }
Roland McGrath96dc5142003-01-20 10:23:04 +00001432 else if (((tcp->flags & (TCB_INSYSCALL|TCB_WAITEXECVE))
1433 == (TCB_INSYSCALL|TCB_WAITEXECVE))
1434 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1435 /*
1436 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1437 * flag set for the post-execve SIGTRAP to see and reset.
1438 */
1439 gpr2 = 0;
1440 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001441#elif defined (POWERPC)
1442# define SO_MASK 0x10000000
Roland McGratheb285352003-01-14 09:59:00 +00001443 if (upeek(pid, sizeof(unsigned long)*PT_CCR, &flags) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001444 return -1;
Roland McGratheb285352003-01-14 09:59:00 +00001445 if (upeek(pid, sizeof(unsigned long)*PT_R3, &result) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001446 return -1;
1447 if (flags & SO_MASK)
1448 result = -result;
1449#elif defined (M68K)
1450 if (upeek(pid, 4*PT_D0, &d0) < 0)
1451 return -1;
1452 if (d0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1453 if (debug)
1454 fprintf(stderr, "stray syscall exit: d0 = %ld\n", d0);
1455 return 0;
1456 }
1457#elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001458 /*
1459 * Nothing required
1460 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001461#elif defined (HPPA)
1462 if (upeek(pid, PT_GR28, &r28) < 0)
1463 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001464#elif defined(IA64)
1465 if (upeek(pid, PT_R10, &r10) < 0)
1466 return -1;
1467 if (upeek(pid, PT_R8, &r8) < 0)
1468 return -1;
1469 if (ia32 && r8 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1470 if (debug)
1471 fprintf(stderr, "stray syscall exit: r8 = %ld\n", r8);
1472 return 0;
1473 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001474#endif
1475#endif /* LINUX */
Pavel Machek4dc3b142000-02-01 17:58:41 +00001476 return 1;
1477}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001478
Roland McGratha4d48532005-06-08 20:45:28 +00001479static int
Pavel Machek4dc3b142000-02-01 17:58:41 +00001480get_error(tcp)
1481struct tcb *tcp;
1482{
1483 int u_error = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001484#ifdef LINUX
Michal Ludvig10a88d02002-10-07 14:31:00 +00001485#if defined(S390) || defined(S390X)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001486 if (gpr2 && (unsigned) -gpr2 < nerrnos) {
1487 tcp->u_rval = -1;
1488 u_error = -gpr2;
1489 }
1490 else {
1491 tcp->u_rval = gpr2;
1492 u_error = 0;
1493 }
Michal Ludvig10a88d02002-10-07 14:31:00 +00001494#else /* !S390 && !S390X */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001495#ifdef I386
1496 if (eax < 0 && -eax < nerrnos) {
1497 tcp->u_rval = -1;
1498 u_error = -eax;
1499 }
1500 else {
1501 tcp->u_rval = eax;
1502 u_error = 0;
1503 }
1504#else /* !I386 */
Michal Ludvig0e035502002-09-23 15:41:01 +00001505#ifdef X86_64
1506 if (rax < 0 && -rax < nerrnos) {
1507 tcp->u_rval = -1;
1508 u_error = -rax;
1509 }
1510 else {
1511 tcp->u_rval = rax;
1512 u_error = 0;
1513 }
1514#else
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001515#ifdef IA64
1516 if (ia32) {
1517 int err;
1518
1519 err = (int)r8;
1520 if (err < 0 && -err < nerrnos) {
1521 tcp->u_rval = -1;
1522 u_error = -err;
1523 }
1524 else {
1525 tcp->u_rval = err;
1526 u_error = 0;
1527 }
1528 } else {
1529 if (r10) {
1530 tcp->u_rval = -1;
1531 u_error = r8;
1532 } else {
1533 tcp->u_rval = r8;
1534 u_error = 0;
1535 }
1536 }
1537#else /* !IA64 */
Wichert Akkermanf90da011999-10-31 21:15:38 +00001538#ifdef MIPS
1539 if (a3) {
1540 tcp->u_rval = -1;
1541 u_error = r2;
1542 } else {
1543 tcp->u_rval = r2;
1544 u_error = 0;
1545 }
1546#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001547#ifdef POWERPC
Roland McGrath190f8dd2004-01-13 10:13:44 +00001548 if (result && (unsigned long) -result < nerrnos) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001549 tcp->u_rval = -1;
1550 u_error = -result;
1551 }
1552 else {
1553 tcp->u_rval = result;
1554 u_error = 0;
1555 }
1556#else /* !POWERPC */
1557#ifdef M68K
1558 if (d0 && (unsigned) -d0 < nerrnos) {
1559 tcp->u_rval = -1;
1560 u_error = -d0;
1561 }
1562 else {
1563 tcp->u_rval = d0;
1564 u_error = 0;
1565 }
1566#else /* !M68K */
1567#ifdef ARM
Roland McGrath0f87c492003-06-03 23:29:04 +00001568 if (regs.ARM_r0 && (unsigned) -regs.ARM_r0 < nerrnos) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001569 tcp->u_rval = -1;
Roland McGrath0f87c492003-06-03 23:29:04 +00001570 u_error = -regs.ARM_r0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001571 }
1572 else {
Roland McGrath0f87c492003-06-03 23:29:04 +00001573 tcp->u_rval = regs.ARM_r0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001574 u_error = 0;
1575 }
1576#else /* !ARM */
1577#ifdef ALPHA
1578 if (a3) {
1579 tcp->u_rval = -1;
1580 u_error = r0;
1581 }
1582 else {
1583 tcp->u_rval = r0;
1584 u_error = 0;
1585 }
1586#else /* !ALPHA */
1587#ifdef SPARC
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001588 if (regs.r_psr & PSR_C) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001589 tcp->u_rval = -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001590 u_error = regs.r_o0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001591 }
1592 else {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001593 tcp->u_rval = regs.r_o0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001594 u_error = 0;
1595 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001596#else /* !SPARC */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001597#ifdef SPARC64
1598 if (regs.r_tstate & 0x1100000000UL) {
1599 tcp->u_rval = -1;
1600 u_error = regs.r_o0;
1601 }
1602 else {
1603 tcp->u_rval = regs.r_o0;
1604 u_error = 0;
1605 }
1606#else /* !SPARC64 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001607#ifdef HPPA
1608 if (r28 && (unsigned) -r28 < nerrnos) {
1609 tcp->u_rval = -1;
1610 u_error = -r28;
1611 }
1612 else {
1613 tcp->u_rval = r28;
1614 u_error = 0;
1615 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00001616#else
1617#ifdef SH
1618 /* interpret R0 as return value or error number */
1619 if (r0 && (unsigned) -r0 < nerrnos) {
1620 tcp->u_rval = -1;
1621 u_error = -r0;
1622 }
1623 else {
1624 tcp->u_rval = r0;
1625 u_error = 0;
1626 }
Roland McGrathe1e584b2003-06-02 19:18:58 +00001627#else
Roland McGrathf5a47772003-06-26 22:40:42 +00001628#ifdef SH64
Roland McGrathe1e584b2003-06-02 19:18:58 +00001629 /* interpret result as return value or error number */
1630 if (r9 && (unsigned) -r9 < nerrnos) {
1631 tcp->u_rval = -1;
1632 u_error = -r9;
1633 }
1634 else {
1635 tcp->u_rval = r9;
1636 u_error = 0;
1637 }
Roland McGrathf5a47772003-06-26 22:40:42 +00001638#endif /* SH64 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001639#endif /* SH */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001640#endif /* HPPA */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001641#endif /* SPARC */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001642#endif /* SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001643#endif /* ALPHA */
1644#endif /* ARM */
1645#endif /* M68K */
1646#endif /* POWERPC */
Wichert Akkermanf90da011999-10-31 21:15:38 +00001647#endif /* MIPS */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001648#endif /* IA64 */
Michal Ludvig0e035502002-09-23 15:41:01 +00001649#endif /* X86_64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001650#endif /* I386 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001651#endif /* S390 || S390X */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001652#endif /* LINUX */
1653#ifdef SUNOS4
1654 /* get error code from user struct */
1655 if (upeek(pid, uoff(u_error), &u_error) < 0)
1656 return -1;
1657 u_error >>= 24; /* u_error is a char */
1658
1659 /* get system call return value */
1660 if (upeek(pid, uoff(u_rval1), &tcp->u_rval) < 0)
1661 return -1;
1662#endif /* SUNOS4 */
1663#ifdef SVR4
1664#ifdef SPARC
1665 /* Judicious guessing goes a long way. */
1666 if (tcp->status.pr_reg[R_PSR] & 0x100000) {
1667 tcp->u_rval = -1;
1668 u_error = tcp->status.pr_reg[R_O0];
1669 }
1670 else {
1671 tcp->u_rval = tcp->status.pr_reg[R_O0];
1672 u_error = 0;
1673 }
1674#endif /* SPARC */
1675#ifdef I386
1676 /* Wanna know how to kill an hour single-stepping? */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001677 if (tcp->status.PR_REG[EFL] & 0x1) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001678 tcp->u_rval = -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001679 u_error = tcp->status.PR_REG[EAX];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001680 }
1681 else {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001682 tcp->u_rval = tcp->status.PR_REG[EAX];
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001683#ifdef HAVE_LONG_LONG
1684 tcp->u_lrval =
1685 ((unsigned long long) tcp->status.PR_REG[EDX] << 32) +
1686 tcp->status.PR_REG[EAX];
1687#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001688 u_error = 0;
1689 }
1690#endif /* I386 */
Michal Ludvig0e035502002-09-23 15:41:01 +00001691#ifdef X86_64
1692 /* Wanna know how to kill an hour single-stepping? */
1693 if (tcp->status.PR_REG[EFLAGS] & 0x1) {
1694 tcp->u_rval = -1;
1695 u_error = tcp->status.PR_REG[RAX];
1696 }
1697 else {
1698 tcp->u_rval = tcp->status.PR_REG[RAX];
1699 u_error = 0;
1700 }
1701#endif /* X86_64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001702#ifdef MIPS
1703 if (tcp->status.pr_reg[CTX_A3]) {
1704 tcp->u_rval = -1;
1705 u_error = tcp->status.pr_reg[CTX_V0];
1706 }
1707 else {
1708 tcp->u_rval = tcp->status.pr_reg[CTX_V0];
1709 u_error = 0;
1710 }
1711#endif /* MIPS */
1712#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001713#ifdef FREEBSD
1714 if (regs.r_eflags & PSL_C) {
1715 tcp->u_rval = -1;
1716 u_error = regs.r_eax;
1717 } else {
1718 tcp->u_rval = regs.r_eax;
1719 tcp->u_lrval =
1720 ((unsigned long long) regs.r_edx << 32) + regs.r_eax;
1721 u_error = 0;
1722 }
Roland McGrath761b5d72002-12-15 23:58:31 +00001723#endif /* FREEBSD */
Pavel Machek4dc3b142000-02-01 17:58:41 +00001724 tcp->u_error = u_error;
1725 return 1;
1726}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001727
Roland McGrathb69f81b2002-12-21 23:25:18 +00001728int
1729force_result(tcp, error, rval)
1730 struct tcb *tcp;
1731 int error;
1732 long rval;
1733{
1734#ifdef LINUX
1735#if defined(S390) || defined(S390X)
1736 gpr2 = error ? -error : rval;
Roland McGrathb69f81b2002-12-21 23:25:18 +00001737 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_GPR2, gpr2) < 0)
1738 return -1;
1739#else /* !S390 && !S390X */
1740#ifdef I386
1741 eax = error ? -error : rval;
1742 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(EAX * 4), eax) < 0)
1743 return -1;
1744#else /* !I386 */
1745#ifdef X86_64
1746 rax = error ? -error : rval;
Roland McGrath998fac72004-06-23 01:40:45 +00001747 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(RAX * 8), rax) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001748 return -1;
1749#else
1750#ifdef IA64
1751 if (ia32) {
1752 r8 = error ? -error : rval;
1753 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0)
1754 return -1;
1755 }
1756 else {
1757 if (error) {
1758 r8 = error;
1759 r10 = -1;
1760 }
1761 else {
1762 r8 = rval;
1763 r10 = 0;
1764 }
1765 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0 ||
1766 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R10), r10) < 0)
1767 return -1;
1768 }
1769#else /* !IA64 */
1770#ifdef MIPS
1771 if (error) {
1772 r2 = error;
1773 a3 = -1;
1774 }
1775 else {
1776 r2 = rval;
1777 a3 = 0;
1778 }
1779 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1780 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), r2) < 0)
1781 return -1;
1782#else
1783#ifdef POWERPC
Roland McGratheb285352003-01-14 09:59:00 +00001784 if (upeek(tcp->pid, sizeof(unsigned long)*PT_CCR, &flags) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001785 return -1;
1786 if (error) {
1787 flags |= SO_MASK;
1788 result = error;
1789 }
1790 else {
1791 flags &= ~SO_MASK;
1792 result = rval;
1793 }
Roland McGratheb285352003-01-14 09:59:00 +00001794 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_CCR), flags) < 0 ||
1795 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_R3), result) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001796 return -1;
1797#else /* !POWERPC */
1798#ifdef M68K
1799 d0 = error ? -error : rval;
1800 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_D0), d0) < 0)
1801 return -1;
1802#else /* !M68K */
1803#ifdef ARM
Roland McGrath7c051d22003-06-26 22:29:32 +00001804 regs.ARM_r0 = error ? -error : rval;
1805 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*0), regs.ARM_r0) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001806 return -1;
1807#else /* !ARM */
1808#ifdef ALPHA
1809 if (error) {
1810 a3 = -1;
1811 r0 = error;
1812 }
1813 else {
1814 a3 = 0;
1815 r0 = rval;
1816 }
1817 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1818 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R0), r0) < 0)
1819 return -1;
1820#else /* !ALPHA */
1821#ifdef SPARC
1822 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1823 return -1;
1824 if (error) {
1825 regs.r_psr |= PSR_C;
1826 regs.r_o0 = error;
1827 }
1828 else {
1829 regs.r_psr &= ~PSR_C;
1830 regs.r_o0 = rval;
1831 }
1832 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1833 return -1;
1834#else /* !SPARC */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001835#ifdef SPARC64
1836 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1837 return -1;
1838 if (error) {
1839 regs.r_tstate |= 0x1100000000UL;
1840 regs.r_o0 = error;
1841 }
1842 else {
1843 regs.r_tstate &= ~0x1100000000UL;
1844 regs.r_o0 = rval;
1845 }
1846 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1847 return -1;
1848#else /* !SPARC64 */
Roland McGrathb69f81b2002-12-21 23:25:18 +00001849#ifdef HPPA
1850 r28 = error ? -error : rval;
1851 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR28), r28) < 0)
1852 return -1;
1853#else
1854#ifdef SH
1855 r0 = error ? -error : rval;
1856 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*REG_REG0), r0) < 0)
1857 return -1;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001858#else
Roland McGrathf5a47772003-06-26 22:40:42 +00001859#ifdef SH64
Roland McGrathe1e584b2003-06-02 19:18:58 +00001860 r9 = error ? -error : rval;
1861 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_GENERAL(9), r9) < 0)
1862 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001863#endif /* SH64 */
Roland McGrathb69f81b2002-12-21 23:25:18 +00001864#endif /* SH */
1865#endif /* HPPA */
1866#endif /* SPARC */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001867#endif /* SPARC64 */
Roland McGrathb69f81b2002-12-21 23:25:18 +00001868#endif /* ALPHA */
1869#endif /* ARM */
1870#endif /* M68K */
1871#endif /* POWERPC */
1872#endif /* MIPS */
1873#endif /* IA64 */
1874#endif /* X86_64 */
1875#endif /* I386 */
1876#endif /* S390 || S390X */
1877#endif /* LINUX */
1878#ifdef SUNOS4
1879 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_error),
1880 error << 24) < 0 ||
1881 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_rval1), rval) < 0)
1882 return -1;
1883#endif /* SUNOS4 */
1884#ifdef SVR4
1885 /* XXX no clue */
1886 return -1;
1887#endif /* SVR4 */
1888#ifdef FREEBSD
1889 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1890 perror("pread");
1891 return -1;
1892 }
1893 if (error) {
1894 regs.r_eflags |= PSL_C;
1895 regs.r_eax = error;
1896 }
1897 else {
1898 regs.r_eflags &= ~PSL_C;
1899 regs.r_eax = rval;
1900 }
1901 if (pwrite(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1902 perror("pwrite");
1903 return -1;
1904 }
1905#endif /* FREEBSD */
1906
1907 /* All branches reach here on success (only). */
1908 tcp->u_error = error;
1909 tcp->u_rval = rval;
1910 return 0;
1911}
1912
Roland McGratha4d48532005-06-08 20:45:28 +00001913static int
1914syscall_enter(tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001915struct tcb *tcp;
1916{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001917#ifndef USE_PROCFS
Pavel Machek4dc3b142000-02-01 17:58:41 +00001918 int pid = tcp->pid;
Roland McGrath761b5d72002-12-15 23:58:31 +00001919#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001920#ifdef LINUX
Michal Ludvig10a88d02002-10-07 14:31:00 +00001921#if defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001922 {
1923 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001924 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1925 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00001926 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001927 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001928 for (i = 0; i < tcp->u_nargs; i++) {
Michal Ludvig10a88d02002-10-07 14:31:00 +00001929 if (upeek(pid,i==0 ? PT_ORIGGPR2:PT_GPR2+i*sizeof(long), &tcp->u_arg[i]) < 0)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001930 return -1;
1931 }
1932 }
1933#elif defined (ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001934 {
1935 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001936 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1937 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00001938 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001939 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001940 for (i = 0; i < tcp->u_nargs; i++) {
Wichert Akkermanb859bea1999-04-18 22:50:50 +00001941 /* WTA: if scno is out-of-bounds this will bomb. Add range-check
1942 * for scno somewhere above here!
1943 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001944 if (upeek(pid, REG_A0+i, &tcp->u_arg[i]) < 0)
1945 return -1;
1946 }
1947 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001948#elif defined (IA64)
1949 {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001950 if (!ia32) {
1951 unsigned long *out0, *rbs_end, cfm, sof, sol, i;
1952 /* be backwards compatible with kernel < 2.4.4... */
1953# ifndef PT_RBS_END
1954# define PT_RBS_END PT_AR_BSP
1955# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001956
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001957 if (upeek(pid, PT_RBS_END, (long *) &rbs_end) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001958 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001959 if (upeek(pid, PT_CFM, (long *) &cfm) < 0)
1960 return -1;
1961
1962 sof = (cfm >> 0) & 0x7f;
1963 sol = (cfm >> 7) & 0x7f;
1964 out0 = ia64_rse_skip_regs(rbs_end, -sof + sol);
1965
1966 if (tcp->scno >= 0 && tcp->scno < nsyscalls
1967 && sysent[tcp->scno].nargs != -1)
1968 tcp->u_nargs = sysent[tcp->scno].nargs;
1969 else
1970 tcp->u_nargs = MAX_ARGS;
1971 for (i = 0; i < tcp->u_nargs; ++i) {
1972 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1973 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1974 return -1;
1975 }
1976 } else {
1977 int i;
1978
1979 if (/* EBX = out0 */
1980 upeek(pid, PT_R11, (long *) &tcp->u_arg[0]) < 0
1981 /* ECX = out1 */
1982 || upeek(pid, PT_R9, (long *) &tcp->u_arg[1]) < 0
1983 /* EDX = out2 */
1984 || upeek(pid, PT_R10, (long *) &tcp->u_arg[2]) < 0
1985 /* ESI = out3 */
1986 || upeek(pid, PT_R14, (long *) &tcp->u_arg[3]) < 0
1987 /* EDI = out4 */
1988 || upeek(pid, PT_R15, (long *) &tcp->u_arg[4]) < 0
1989 /* EBP = out5 */
1990 || upeek(pid, PT_R13, (long *) &tcp->u_arg[5]) < 0)
1991 return -1;
1992
1993 for (i = 0; i < 6; ++i)
1994 /* truncate away IVE sign-extension */
1995 tcp->u_arg[i] &= 0xffffffff;
1996
1997 if (tcp->scno >= 0 && tcp->scno < nsyscalls
1998 && sysent[tcp->scno].nargs != -1)
1999 tcp->u_nargs = sysent[tcp->scno].nargs;
2000 else
2001 tcp->u_nargs = 5;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002002 }
2003 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00002004#elif defined (MIPS)
2005 {
2006 long sp;
2007 int i, nargs;
2008
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002009 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2010 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002011 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002012 nargs = tcp->u_nargs = MAX_ARGS;
Wichert Akkermanf90da011999-10-31 21:15:38 +00002013 if(nargs > 4) {
2014 if(upeek(pid, REG_SP, &sp) < 0)
2015 return -1;
2016 for(i = 0; i < 4; i++) {
2017 if (upeek(pid, REG_A0 + i, &tcp->u_arg[i])<0)
2018 return -1;
2019 }
2020 umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]),
2021 (char *)(tcp->u_arg + 4));
2022 } else {
2023 for(i = 0; i < nargs; i++) {
2024 if (upeek(pid, REG_A0 + i, &tcp->u_arg[i]) < 0)
2025 return -1;
2026 }
2027 }
2028 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002029#elif defined (POWERPC)
Roland McGrath761b5d72002-12-15 23:58:31 +00002030#ifndef PT_ORIG_R3
2031#define PT_ORIG_R3 34
2032#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002033 {
2034 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002035 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2036 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002037 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002038 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002039 for (i = 0; i < tcp->u_nargs; i++) {
Roland McGratheb285352003-01-14 09:59:00 +00002040 if (upeek(pid, (i==0) ?
2041 (sizeof(unsigned long)*PT_ORIG_R3) :
2042 ((i+PT_R3)*sizeof(unsigned long)),
2043 &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002044 return -1;
2045 }
2046 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002047#elif defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002048 {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002049 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002050
2051 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2052 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002053 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002054 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002055 for (i = 0; i < tcp->u_nargs; i++)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002056 tcp->u_arg[i] = *((&regs.r_o0) + i);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002057 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002058#elif defined (HPPA)
2059 {
2060 int i;
2061
2062 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2063 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002064 else
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002065 tcp->u_nargs = MAX_ARGS;
2066 for (i = 0; i < tcp->u_nargs; i++) {
2067 if (upeek(pid, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
2068 return -1;
2069 }
2070 }
Roland McGrath0f87c492003-06-03 23:29:04 +00002071#elif defined(ARM)
2072 {
2073 int i;
2074
2075 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2076 tcp->u_nargs = sysent[tcp->scno].nargs;
2077 else
2078 tcp->u_nargs = MAX_ARGS;
2079 for (i = 0; i < tcp->u_nargs; i++)
2080 tcp->u_arg[i] = regs.uregs[i];
2081 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00002082#elif defined(SH)
2083 {
Roland McGrath761b5d72002-12-15 23:58:31 +00002084 int i;
Wichert Akkermanccef6372002-05-01 16:39:22 +00002085 static int syscall_regs[] = {
2086 REG_REG0+4, REG_REG0+5, REG_REG0+6, REG_REG0+7,
2087 REG_REG0, REG_REG0+1, REG_REG0+2
2088 };
2089
2090 tcp->u_nargs = sysent[tcp->scno].nargs;
2091 for (i = 0; i < tcp->u_nargs; i++) {
2092 if (upeek(pid, 4*syscall_regs[i], &tcp->u_arg[i]) < 0)
2093 return -1;
2094 }
2095 }
Roland McGrathf5a47772003-06-26 22:40:42 +00002096#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00002097 {
2098 int i;
2099 /* Registers used by SH5 Linux system calls for parameters */
2100 static int syscall_regs[] = { 2, 3, 4, 5, 6, 7 };
2101
2102 /*
2103 * TODO: should also check that the number of arguments encoded
2104 * in the trap number matches the number strace expects.
2105 */
2106 /*
2107 assert(sysent[tcp->scno].nargs <
2108 sizeof(syscall_regs)/sizeof(syscall_regs[0]));
2109 */
2110
2111 tcp->u_nargs = sysent[tcp->scno].nargs;
2112 for (i = 0; i < tcp->u_nargs; i++) {
2113 if (upeek(pid, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
2114 return -1;
2115 }
2116 }
2117
Michal Ludvig0e035502002-09-23 15:41:01 +00002118#elif defined(X86_64)
2119 {
2120 int i;
2121 static int argreg[SUPPORTED_PERSONALITIES][MAX_ARGS] = {
2122 {RDI,RSI,RDX,R10,R8,R9}, /* x86-64 ABI */
Roland McGrath5a9c6ad2005-02-02 03:06:52 +00002123 {RBX,RCX,RDX,RSI,RDI,RBP} /* i386 ABI */
Michal Ludvig0e035502002-09-23 15:41:01 +00002124 };
Roland McGrath761b5d72002-12-15 23:58:31 +00002125
Michal Ludvig0e035502002-09-23 15:41:01 +00002126 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2127 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002128 else
Michal Ludvig0e035502002-09-23 15:41:01 +00002129 tcp->u_nargs = MAX_ARGS;
2130 for (i = 0; i < tcp->u_nargs; i++) {
2131 if (upeek(pid, argreg[current_personality][i]*8, &tcp->u_arg[i]) < 0)
2132 return -1;
2133 }
2134 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00002135#else /* Other architecture (like i386) (32bits specific) */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002136 {
2137 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002138 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2139 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002140 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002141 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002142 for (i = 0; i < tcp->u_nargs; i++) {
2143 if (upeek(pid, i*4, &tcp->u_arg[i]) < 0)
2144 return -1;
2145 }
2146 }
Roland McGrath761b5d72002-12-15 23:58:31 +00002147#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002148#endif /* LINUX */
2149#ifdef SUNOS4
2150 {
2151 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002152 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2153 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002154 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002155 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002156 for (i = 0; i < tcp->u_nargs; i++) {
2157 struct user *u;
2158
2159 if (upeek(pid, uoff(u_arg[0]) +
2160 (i*sizeof(u->u_arg[0])), &tcp->u_arg[i]) < 0)
2161 return -1;
2162 }
2163 }
2164#endif /* SUNOS4 */
2165#ifdef SVR4
2166#ifdef MIPS
2167 /*
2168 * SGI is broken: even though it has pr_sysarg, it doesn't
2169 * set them on system call entry. Get a clue.
2170 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002171 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002172 tcp->u_nargs = sysent[tcp->scno].nargs;
2173 else
2174 tcp->u_nargs = tcp->status.pr_nsysarg;
2175 if (tcp->u_nargs > 4) {
2176 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2177 4*sizeof(tcp->u_arg[0]));
2178 umoven(tcp, tcp->status.pr_reg[CTX_SP] + 16,
2179 (tcp->u_nargs - 4)*sizeof(tcp->u_arg[0]), (char *) (tcp->u_arg + 4));
2180 }
2181 else {
2182 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2183 tcp->u_nargs*sizeof(tcp->u_arg[0]));
2184 }
John Hughes25299712001-03-06 10:10:06 +00002185#elif UNIXWARE >= 2
2186 /*
2187 * Like SGI, UnixWare doesn't set pr_sysarg until system call exit
2188 */
2189 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2190 tcp->u_nargs = sysent[tcp->scno].nargs;
2191 else
2192 tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;
2193 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
2194 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2195#elif defined (HAVE_PR_SYSCALL)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002196 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002197 tcp->u_nargs = sysent[tcp->scno].nargs;
2198 else
2199 tcp->u_nargs = tcp->status.pr_nsysarg;
2200 {
2201 int i;
2202 for (i = 0; i < tcp->u_nargs; i++)
2203 tcp->u_arg[i] = tcp->status.pr_sysarg[i];
2204 }
John Hughes25299712001-03-06 10:10:06 +00002205#elif defined (I386)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002206 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002207 tcp->u_nargs = sysent[tcp->scno].nargs;
2208 else
2209 tcp->u_nargs = 5;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002210 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002211 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
John Hughes25299712001-03-06 10:10:06 +00002212#else
2213 I DONT KNOW WHAT TO DO
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002214#endif /* !HAVE_PR_SYSCALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002215#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002216#ifdef FREEBSD
2217 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2218 sysent[tcp->scno].nargs > tcp->status.val)
2219 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002220 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002221 tcp->u_nargs = tcp->status.val;
2222 if (tcp->u_nargs < 0)
2223 tcp->u_nargs = 0;
2224 if (tcp->u_nargs > MAX_ARGS)
2225 tcp->u_nargs = MAX_ARGS;
2226 switch(regs.r_eax) {
2227 case SYS___syscall:
2228 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2229 regs.r_esp + sizeof(int) + sizeof(quad_t));
2230 break;
2231 case SYS_syscall:
2232 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2233 regs.r_esp + 2 * sizeof(int));
2234 break;
2235 default:
2236 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2237 regs.r_esp + sizeof(int));
2238 break;
2239 }
2240#endif /* FREEBSD */
Pavel Machek4dc3b142000-02-01 17:58:41 +00002241 return 1;
2242}
2243
2244int
Dmitry V. Levin7d61ff12006-12-21 21:15:04 +00002245trace_syscall(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002246{
2247 int sys_res;
2248 struct timeval tv;
2249 int res;
2250
2251 /* Measure the exit time as early as possible to avoid errors. */
2252 if (dtime && (tcp->flags & TCB_INSYSCALL))
2253 gettimeofday(&tv, NULL);
2254
2255 res = get_scno(tcp);
2256 if (res != 1)
2257 return res;
2258
2259 res = syscall_fixup(tcp);
2260 if (res != 1)
2261 return res;
2262
2263 if (tcp->flags & TCB_INSYSCALL) {
2264 long u_error;
2265 res = get_error(tcp);
2266 if (res != 1)
2267 return res;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002268
2269 internal_syscall(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002270 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2271 !(qual_flags[tcp->scno] & QUAL_TRACE)) {
Pavel Machek4dc3b142000-02-01 17:58:41 +00002272 tcp->flags &= ~TCB_INSYSCALL;
2273 return 0;
2274 }
2275
2276 if (tcp->flags & TCB_REPRINT) {
2277 printleader(tcp);
2278 tprintf("<... ");
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002279 if (tcp->scno >= nsyscalls || tcp->scno < 0)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002280 tprintf("syscall_%lu", tcp->scno);
2281 else
2282 tprintf("%s", sysent[tcp->scno].sys_name);
2283 tprintf(" resumed> ");
2284 }
2285
Dmitry V. Levin7d61ff12006-12-21 21:15:04 +00002286 if (cflag)
2287 return count_syscall(tcp, &tv);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002288
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002289 if (tcp->scno >= nsyscalls || tcp->scno < 0
Pavel Machek4dc3b142000-02-01 17:58:41 +00002290 || (qual_flags[tcp->scno] & QUAL_RAW))
2291 sys_res = printargs(tcp);
Michal Ludvig17f8fb32002-11-06 13:17:21 +00002292 else {
2293 if (not_failing_only && tcp->u_error)
Roland McGrath761b5d72002-12-15 23:58:31 +00002294 return 0; /* ignore failed syscalls */
Pavel Machek4dc3b142000-02-01 17:58:41 +00002295 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
Roland McGrath761b5d72002-12-15 23:58:31 +00002296 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002297 u_error = tcp->u_error;
2298 tprintf(") ");
2299 tabto(acolumn);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002300 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2301 qual_flags[tcp->scno] & QUAL_RAW) {
Pavel Machek4dc3b142000-02-01 17:58:41 +00002302 if (u_error)
2303 tprintf("= -1 (errno %ld)", u_error);
2304 else
2305 tprintf("= %#lx", tcp->u_rval);
2306 }
2307 else if (!(sys_res & RVAL_NONE) && u_error) {
2308 switch (u_error) {
2309#ifdef LINUX
2310 case ERESTARTSYS:
2311 tprintf("= ? ERESTARTSYS (To be restarted)");
2312 break;
2313 case ERESTARTNOINTR:
2314 tprintf("= ? ERESTARTNOINTR (To be restarted)");
2315 break;
2316 case ERESTARTNOHAND:
2317 tprintf("= ? ERESTARTNOHAND (To be restarted)");
2318 break;
Roland McGrath9c555e72003-07-09 09:47:59 +00002319 case ERESTART_RESTARTBLOCK:
2320 tprintf("= ? ERESTART_RESTARTBLOCK (To be restarted)");
2321 break;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002322#endif /* LINUX */
2323 default:
2324 tprintf("= -1 ");
Wichert Akkerman4527dae2002-03-31 19:03:29 +00002325 if (u_error < 0)
2326 tprintf("E??? (errno %ld)", u_error);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002327 else if (u_error < nerrnos)
Roland McGrath761b5d72002-12-15 23:58:31 +00002328 tprintf("%s (%s)", errnoent[u_error],
2329 strerror(u_error));
Pavel Machek4dc3b142000-02-01 17:58:41 +00002330 else
Roland McGrath761b5d72002-12-15 23:58:31 +00002331 tprintf("ERRNO_%ld (%s)", u_error,
2332 strerror(u_error));
Pavel Machek4dc3b142000-02-01 17:58:41 +00002333 break;
2334 }
2335 }
2336 else {
2337 if (sys_res & RVAL_NONE)
2338 tprintf("= ?");
2339 else {
2340 switch (sys_res & RVAL_MASK) {
2341 case RVAL_HEX:
2342 tprintf("= %#lx", tcp->u_rval);
2343 break;
2344 case RVAL_OCTAL:
2345 tprintf("= %#lo", tcp->u_rval);
2346 break;
2347 case RVAL_UDECIMAL:
2348 tprintf("= %lu", tcp->u_rval);
2349 break;
2350 case RVAL_DECIMAL:
2351 tprintf("= %ld", tcp->u_rval);
2352 break;
Wichert Akkerman16a03d22000-08-10 02:14:04 +00002353#ifdef HAVE_LONG_LONG
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002354 case RVAL_LHEX:
2355 tprintf("= %#llx", tcp->u_lrval);
Wichert Akkerman16a03d22000-08-10 02:14:04 +00002356 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002357 case RVAL_LOCTAL:
2358 tprintf("= %#llo", tcp->u_lrval);
2359 break;
2360 case RVAL_LUDECIMAL:
2361 tprintf("= %llu", tcp->u_lrval);
2362 break;
2363 case RVAL_LDECIMAL:
2364 tprintf("= %lld", tcp->u_lrval);
2365 break;
Wichert Akkerman16a03d22000-08-10 02:14:04 +00002366#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00002367 default:
2368 fprintf(stderr,
2369 "invalid rval format\n");
2370 break;
2371 }
2372 }
2373 if ((sys_res & RVAL_STR) && tcp->auxstr)
2374 tprintf(" (%s)", tcp->auxstr);
2375 }
2376 if (dtime) {
2377 tv_sub(&tv, &tv, &tcp->etime);
2378 tprintf(" <%ld.%06ld>",
2379 (long) tv.tv_sec, (long) tv.tv_usec);
2380 }
2381 printtrailer(tcp);
2382
2383 dumpio(tcp);
2384 if (fflush(tcp->outf) == EOF)
2385 return -1;
2386 tcp->flags &= ~TCB_INSYSCALL;
2387 return 0;
2388 }
2389
2390 /* Entering system call */
2391 res = syscall_enter(tcp);
2392 if (res != 1)
2393 return res;
2394
Roland McGrath17352792005-06-07 23:21:26 +00002395 switch (known_scno(tcp)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002396#ifdef LINUX
Roland McGrath17352792005-06-07 23:21:26 +00002397#if !defined (ALPHA) && !defined(SPARC) && !defined(SPARC64) && !defined(MIPS) && !defined(HPPA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002398 case SYS_socketcall:
2399 decode_subcall(tcp, SYS_socket_subcall,
2400 SYS_socket_nsubcalls, deref_style);
2401 break;
2402 case SYS_ipc:
2403 decode_subcall(tcp, SYS_ipc_subcall,
2404 SYS_ipc_nsubcalls, shift_style);
2405 break;
Roland McGrath17352792005-06-07 23:21:26 +00002406#endif /* !ALPHA && !MIPS && !SPARC && !SPARC64 && !HPPA */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002407#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002408 case SYS_socketcall:
2409 sparc_socket_decode (tcp);
2410 break;
2411#endif
2412#endif /* LINUX */
2413#ifdef SVR4
2414#ifdef SYS_pgrpsys_subcall
2415 case SYS_pgrpsys:
2416 decode_subcall(tcp, SYS_pgrpsys_subcall,
2417 SYS_pgrpsys_nsubcalls, shift_style);
2418 break;
2419#endif /* SYS_pgrpsys_subcall */
2420#ifdef SYS_sigcall_subcall
2421 case SYS_sigcall:
2422 decode_subcall(tcp, SYS_sigcall_subcall,
2423 SYS_sigcall_nsubcalls, mask_style);
2424 break;
2425#endif /* SYS_sigcall_subcall */
2426 case SYS_msgsys:
2427 decode_subcall(tcp, SYS_msgsys_subcall,
2428 SYS_msgsys_nsubcalls, shift_style);
2429 break;
2430 case SYS_shmsys:
2431 decode_subcall(tcp, SYS_shmsys_subcall,
2432 SYS_shmsys_nsubcalls, shift_style);
2433 break;
2434 case SYS_semsys:
2435 decode_subcall(tcp, SYS_semsys_subcall,
2436 SYS_semsys_nsubcalls, shift_style);
2437 break;
2438#if 0 /* broken */
2439 case SYS_utssys:
2440 decode_subcall(tcp, SYS_utssys_subcall,
2441 SYS_utssys_nsubcalls, shift_style);
2442 break;
2443#endif
2444 case SYS_sysfs:
2445 decode_subcall(tcp, SYS_sysfs_subcall,
2446 SYS_sysfs_nsubcalls, shift_style);
2447 break;
2448 case SYS_spcall:
2449 decode_subcall(tcp, SYS_spcall_subcall,
2450 SYS_spcall_nsubcalls, shift_style);
2451 break;
2452#ifdef SYS_context_subcall
2453 case SYS_context:
2454 decode_subcall(tcp, SYS_context_subcall,
2455 SYS_context_nsubcalls, shift_style);
2456 break;
2457#endif /* SYS_context_subcall */
Wichert Akkerman8829a551999-06-11 13:18:40 +00002458#ifdef SYS_door_subcall
2459 case SYS_door:
2460 decode_subcall(tcp, SYS_door_subcall,
2461 SYS_door_nsubcalls, door_style);
2462 break;
2463#endif /* SYS_door_subcall */
John Hughesbdf48f52001-03-06 15:08:09 +00002464#ifdef SYS_kaio_subcall
2465 case SYS_kaio:
2466 decode_subcall(tcp, SYS_kaio_subcall,
2467 SYS_kaio_nsubcalls, shift_style);
2468 break;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002469#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002470#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002471#ifdef FREEBSD
2472 case SYS_msgsys:
2473 case SYS_shmsys:
2474 case SYS_semsys:
2475 decode_subcall(tcp, 0, 0, table_style);
2476 break;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002477#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002478#ifdef SUNOS4
2479 case SYS_semsys:
2480 decode_subcall(tcp, SYS_semsys_subcall,
2481 SYS_semsys_nsubcalls, shift_style);
2482 break;
2483 case SYS_msgsys:
2484 decode_subcall(tcp, SYS_msgsys_subcall,
2485 SYS_msgsys_nsubcalls, shift_style);
2486 break;
2487 case SYS_shmsys:
2488 decode_subcall(tcp, SYS_shmsys_subcall,
2489 SYS_shmsys_nsubcalls, shift_style);
2490 break;
2491#endif
2492 }
2493
2494 internal_syscall(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002495 if (tcp->scno >=0 && tcp->scno < nsyscalls && !(qual_flags[tcp->scno] & QUAL_TRACE)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002496 tcp->flags |= TCB_INSYSCALL;
2497 return 0;
2498 }
2499
2500 if (cflag) {
2501 gettimeofday(&tcp->etime, NULL);
2502 tcp->flags |= TCB_INSYSCALL;
2503 return 0;
2504 }
2505
2506 printleader(tcp);
2507 tcp->flags &= ~TCB_REPRINT;
2508 tcp_last = tcp;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002509 if (tcp->scno >= nsyscalls || tcp->scno < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002510 tprintf("syscall_%lu(", tcp->scno);
2511 else
2512 tprintf("%s(", sysent[tcp->scno].sys_name);
Roland McGrath761b5d72002-12-15 23:58:31 +00002513 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002514 ((qual_flags[tcp->scno] & QUAL_RAW) && tcp->scno != SYS_exit))
2515 sys_res = printargs(tcp);
2516 else
2517 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2518 if (fflush(tcp->outf) == EOF)
2519 return -1;
2520 tcp->flags |= TCB_INSYSCALL;
2521 /* Measure the entrance time as late as possible to avoid errors. */
2522 if (dtime)
2523 gettimeofday(&tcp->etime, NULL);
2524 return sys_res;
2525}
2526
2527int
2528printargs(tcp)
2529struct tcb *tcp;
2530{
2531 if (entering(tcp)) {
2532 int i;
2533
2534 for (i = 0; i < tcp->u_nargs; i++)
2535 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
2536 }
2537 return 0;
2538}
2539
2540long
2541getrval2(tcp)
2542struct tcb *tcp;
2543{
2544 long val = -1;
2545
2546#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002547#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002548 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002549 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
2550 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002551 val = regs.r_o1;
Roland McGrath6b1d43e2003-03-31 01:05:01 +00002552#elif defined(SH)
2553 if (upeek(tcp->pid, 4*(REG_REG0+1), &val) < 0)
2554 return -1;
Roland McGrathb4ce1762004-03-01 20:30:48 +00002555#elif defined(IA64)
2556 if (upeek(tcp->pid, PT_R9, &val) < 0)
2557 return -1;
Roland McGrath920e6bb2005-03-15 02:15:20 +00002558#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002559#endif /* LINUX */
2560
2561#ifdef SUNOS4
2562 if (upeek(tcp->pid, uoff(u_rval2), &val) < 0)
2563 return -1;
2564#endif /* SUNOS4 */
2565
2566#ifdef SVR4
2567#ifdef SPARC
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002568 val = tcp->status.PR_REG[R_O1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002569#endif /* SPARC */
2570#ifdef I386
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002571 val = tcp->status.PR_REG[EDX];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002572#endif /* I386 */
Michal Ludvig0e035502002-09-23 15:41:01 +00002573#ifdef X86_64
2574 val = tcp->status.PR_REG[RDX];
2575#endif /* X86_64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002576#ifdef MIPS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002577 val = tcp->status.PR_REG[CTX_V1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002578#endif /* MIPS */
2579#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002580#ifdef FREEBSD
2581 struct reg regs;
2582 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
2583 val = regs.r_edx;
Roland McGrath761b5d72002-12-15 23:58:31 +00002584#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002585 return val;
2586}
2587
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +00002588#ifdef SUNOS4
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002589/*
2590 * Apparently, indirect system calls have already be converted by ptrace(2),
2591 * so if you see "indir" this program has gone astray.
2592 */
2593int
2594sys_indir(tcp)
2595struct tcb *tcp;
2596{
2597 int i, scno, nargs;
2598
2599 if (entering(tcp)) {
2600 if ((scno = tcp->u_arg[0]) > nsyscalls) {
2601 fprintf(stderr, "Bogus syscall: %u\n", scno);
2602 return 0;
2603 }
2604 nargs = sysent[scno].nargs;
2605 tprintf("%s", sysent[scno].sys_name);
2606 for (i = 0; i < nargs; i++)
2607 tprintf(", %#lx", tcp->u_arg[i+1]);
2608 }
2609 return 0;
2610}
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +00002611#endif /* SUNOS4 */