blob: 1ee6ce19e11c1809072a66cc4e21f9927d8e8997 [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) {
1049 /*
1050 * Note: we only deal with only 32-bit CPUs here.
1051 */
1052 if (regs.ARM_cpsr & 0x20) {
1053 /*
1054 * Get the Thumb-mode system call number
1055 */
1056 scno = regs.ARM_r7;
1057 } else {
1058 /*
1059 * Get the ARM-mode system call number
1060 */
1061 errno = 0;
1062 scno = ptrace(PTRACE_PEEKTEXT, pid, (void *)(regs.ARM_pc - 4), NULL);
1063 if (errno)
1064 return -1;
1065
1066 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
1067 tcp->flags &= ~TCB_WAITEXECVE;
1068 return 0;
1069 }
1070
Roland McGrathf691bd22006-04-25 07:34:41 +00001071 /* Handle the EABI syscall convention. We do not
1072 bother converting structures between the two
1073 ABIs, but basic functionality should work even
1074 if strace and the traced program have different
1075 ABIs. */
1076 if (scno == 0xef000000) {
1077 scno = regs.ARM_r7;
1078 } else {
1079 if ((scno & 0x0ff00000) != 0x0f900000) {
1080 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1081 scno);
1082 return -1;
1083 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001084
Roland McGrathf691bd22006-04-25 07:34:41 +00001085 /*
1086 * Fixup the syscall number
1087 */
1088 scno &= 0x000fffff;
1089 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001090 }
1091
1092 if (tcp->flags & TCB_INSYSCALL) {
1093 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1094 tcp->flags &= ~TCB_INSYSCALL;
1095 }
1096 } else {
1097 if (!(tcp->flags & TCB_INSYSCALL)) {
1098 fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
1099 tcp->flags |= TCB_INSYSCALL;
1100 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001101 }
1102#elif defined (M68K)
1103 if (upeek(pid, 4*PT_ORIG_D0, &scno) < 0)
1104 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001105#elif defined (MIPS)
1106 if (upeek(pid, REG_A3, &a3) < 0)
1107 return -1;
1108
1109 if(!(tcp->flags & TCB_INSYSCALL)) {
1110 if (upeek(pid, REG_V0, &scno) < 0)
1111 return -1;
1112
1113 if (scno < 0 || scno > nsyscalls) {
1114 if(a3 == 0 || a3 == -1) {
1115 if(debug)
1116 fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
1117 return 0;
1118 }
1119 }
1120 } else {
1121 if (upeek(pid, REG_V0, &r2) < 0)
1122 return -1;
1123 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001124#elif defined (ALPHA)
1125 if (upeek(pid, REG_A3, &a3) < 0)
1126 return -1;
1127
1128 if (!(tcp->flags & TCB_INSYSCALL)) {
1129 if (upeek(pid, REG_R0, &scno) < 0)
1130 return -1;
1131
1132 /* Check if we return from execve. */
1133 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1134 tcp->flags &= ~TCB_WAITEXECVE;
1135 return 0;
1136 }
1137
1138 /*
1139 * Do some sanity checks to figure out if it's
1140 * really a syscall entry
1141 */
1142 if (scno < 0 || scno > nsyscalls) {
1143 if (a3 == 0 || a3 == -1) {
1144 if (debug)
1145 fprintf (stderr, "stray syscall exit: r0 = %ld\n", scno);
1146 return 0;
1147 }
1148 }
1149 }
1150 else {
1151 if (upeek(pid, REG_R0, &r0) < 0)
1152 return -1;
1153 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001154#elif defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001155 /* Everything we need is in the current register set. */
1156 if (ptrace(PTRACE_GETREGS,pid,(char *)&regs,0) < 0)
1157 return -1;
1158
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001159 /* If we are entering, then disassemble the syscall trap. */
1160 if (!(tcp->flags & TCB_INSYSCALL)) {
1161 /* Retrieve the syscall trap instruction. */
1162 errno = 0;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001163 trap = ptrace(PTRACE_PEEKTEXT,pid,(char *)regs.r_pc,0);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001164#if defined(SPARC64)
1165 trap >>= 32;
1166#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001167 if (errno)
1168 return -1;
1169
1170 /* Disassemble the trap to see what personality to use. */
1171 switch (trap) {
1172 case 0x91d02010:
1173 /* Linux/SPARC syscall trap. */
1174 set_personality(0);
1175 break;
Wichert Akkermandacfb6e1999-06-03 14:21:07 +00001176 case 0x91d0206d:
1177 /* Linux/SPARC64 syscall trap. */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001178 set_personality(2);
1179 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001180 case 0x91d02000:
1181 /* SunOS syscall trap. (pers 1) */
1182 fprintf(stderr,"syscall: SunOS no support\n");
1183 return -1;
1184 case 0x91d02008:
1185 /* Solaris 2.x syscall trap. (per 2) */
1186 set_personality(1);
Roland McGrath761b5d72002-12-15 23:58:31 +00001187 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001188 case 0x91d02009:
1189 /* NetBSD/FreeBSD syscall trap. */
1190 fprintf(stderr,"syscall: NetBSD/FreeBSD not supported\n");
1191 return -1;
1192 case 0x91d02027:
1193 /* Solaris 2.x gettimeofday */
1194 set_personality(1);
1195 break;
1196 default:
1197 /* Unknown syscall trap. */
1198 if(tcp->flags & TCB_WAITEXECVE) {
1199 tcp->flags &= ~TCB_WAITEXECVE;
1200 return 0;
1201 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001202#if defined (SPARC64)
1203 fprintf(stderr,"syscall: unknown syscall trap %08lx %016lx\n", trap, regs.r_tpc);
1204#else
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001205 fprintf(stderr,"syscall: unknown syscall trap %08x %08x\n", trap, regs.r_pc);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001206#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001207 return -1;
1208 }
1209
1210 /* Extract the system call number from the registers. */
1211 if (trap == 0x91d02027)
1212 scno = 156;
1213 else
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001214 scno = regs.r_g1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001215 if (scno == 0) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001216 scno = regs.r_o0;
1217 memmove (&regs.r_o0, &regs.r_o1, 7*sizeof(regs.r_o0));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001218 }
1219 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001220#elif defined(HPPA)
1221 if (upeek(pid, PT_GR20, &scno) < 0)
1222 return -1;
1223 if (!(tcp->flags & TCB_INSYSCALL)) {
1224 /* Check if we return from execve. */
1225 if ((tcp->flags & TCB_WAITEXECVE)) {
1226 tcp->flags &= ~TCB_WAITEXECVE;
1227 return 0;
1228 }
1229 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00001230#elif defined(SH)
1231 /*
1232 * In the new syscall ABI, the system call number is in R3.
1233 */
1234 if (upeek(pid, 4*(REG_REG0+3), &scno) < 0)
1235 return -1;
1236
1237 if (scno < 0) {
1238 /* Odd as it may seem, a glibc bug has been known to cause
1239 glibc to issue bogus negative syscall numbers. So for
1240 our purposes, make strace print what it *should* have been */
1241 long correct_scno = (scno & 0xff);
1242 if (debug)
1243 fprintf(stderr,
Michal Ludvig53b320f2002-09-23 13:30:09 +00001244 "Detected glibc bug: bogus system call number = %ld, "
1245 "correcting to %ld\n",
Wichert Akkermanccef6372002-05-01 16:39:22 +00001246 scno,
1247 correct_scno);
1248 scno = correct_scno;
1249 }
1250
1251
1252 if (!(tcp->flags & TCB_INSYSCALL)) {
1253 /* Check if we return from execve. */
1254 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1255 tcp->flags &= ~TCB_WAITEXECVE;
1256 return 0;
1257 }
1258 }
Roland McGrathf5a47772003-06-26 22:40:42 +00001259#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001260 if (upeek(pid, REG_SYSCALL, &scno) < 0)
1261 return -1;
1262 scno &= 0xFFFF;
1263
1264 if (!(tcp->flags & TCB_INSYSCALL)) {
1265 /* Check if we return from execve. */
1266 if (tcp->flags & TCB_WAITEXECVE) {
1267 tcp->flags &= ~TCB_WAITEXECVE;
1268 return 0;
1269 }
1270 }
Roland McGrathf5a47772003-06-26 22:40:42 +00001271#endif /* SH64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001272#endif /* LINUX */
1273#ifdef SUNOS4
1274 if (upeek(pid, uoff(u_arg[7]), &scno) < 0)
1275 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001276#elif defined(SH)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001277 /* new syscall ABI returns result in R0 */
1278 if (upeek(pid, 4*REG_REG0, (long *)&r0) < 0)
1279 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001280#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001281 /* ABI defines result returned in r9 */
1282 if (upeek(pid, REG_GENERAL(9), (long *)&r9) < 0)
1283 return -1;
1284
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001285#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001286#ifdef USE_PROCFS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001287#ifdef HAVE_PR_SYSCALL
John Hughes25299712001-03-06 10:10:06 +00001288 scno = tcp->status.PR_SYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001289#else /* !HAVE_PR_SYSCALL */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001290#ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001291 scno = tcp->status.PR_WHAT;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001292#else /* FREEBSD */
1293 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1294 perror("pread");
1295 return -1;
1296 }
1297 switch (regs.r_eax) {
1298 case SYS_syscall:
1299 case SYS___syscall:
1300 pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int));
1301 break;
1302 default:
1303 scno = regs.r_eax;
1304 break;
1305 }
1306#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001307#endif /* !HAVE_PR_SYSCALL */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001308#endif /* USE_PROCFS */
Wichert Akkerman5ae21ea2000-05-01 01:53:59 +00001309 if (!(tcp->flags & TCB_INSYSCALL))
1310 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001311 return 1;
1312}
1313
Pavel Machek4dc3b142000-02-01 17:58:41 +00001314
Roland McGrath17352792005-06-07 23:21:26 +00001315long
1316known_scno(tcp)
1317struct tcb *tcp;
1318{
1319 long scno = tcp->scno;
1320 if (scno >= 0 && scno < nsyscalls && sysent[scno].native_scno != 0)
1321 scno = sysent[scno].native_scno;
1322 else
1323 scno += NR_SYSCALL_BASE;
1324 return scno;
1325}
1326
Roland McGratha4d48532005-06-08 20:45:28 +00001327static int
Pavel Machek4dc3b142000-02-01 17:58:41 +00001328syscall_fixup(tcp)
1329struct tcb *tcp;
1330{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001331#ifndef USE_PROCFS
Pavel Machek4dc3b142000-02-01 17:58:41 +00001332 int pid = tcp->pid;
Roland McGrath761b5d72002-12-15 23:58:31 +00001333#else /* USE_PROCFS */
Roland McGrath17352792005-06-07 23:21:26 +00001334 int scno = known_scno(tcp);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001335
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001336 if (!(tcp->flags & TCB_INSYSCALL)) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001337 if (tcp->status.PR_WHY != PR_SYSENTRY) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001338 if (
1339 scno == SYS_fork
1340#ifdef SYS_vfork
1341 || scno == SYS_vfork
1342#endif /* SYS_vfork */
John Hughes4e36a812001-04-18 15:11:51 +00001343#ifdef SYS_fork1
1344 || scno == SYS_fork1
1345#endif /* SYS_fork1 */
1346#ifdef SYS_forkall
1347 || scno == SYS_forkall
1348#endif /* SYS_forkall */
1349#ifdef SYS_rfork1
1350 || scno == SYS_rfork1
1351#endif /* SYS_fork1 */
1352#ifdef SYS_rforkall
1353 || scno == SYS_rforkall
1354#endif /* SYS_rforkall */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001355 ) {
1356 /* We are returning in the child, fake it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001357 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001358 trace_syscall(tcp);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001359 tcp->status.PR_WHY = PR_SYSEXIT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001360 }
1361 else {
1362 fprintf(stderr, "syscall: missing entry\n");
1363 tcp->flags |= TCB_INSYSCALL;
1364 }
1365 }
1366 }
1367 else {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001368 if (tcp->status.PR_WHY != PR_SYSEXIT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001369 fprintf(stderr, "syscall: missing exit\n");
1370 tcp->flags &= ~TCB_INSYSCALL;
1371 }
1372 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001373#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001374#ifdef SUNOS4
1375 if (!(tcp->flags & TCB_INSYSCALL)) {
1376 if (scno == 0) {
1377 fprintf(stderr, "syscall: missing entry\n");
1378 tcp->flags |= TCB_INSYSCALL;
1379 }
1380 }
1381 else {
1382 if (scno != 0) {
1383 if (debug) {
1384 /*
1385 * This happens when a signal handler
1386 * for a signal which interrupted a
1387 * a system call makes another system call.
1388 */
1389 fprintf(stderr, "syscall: missing exit\n");
1390 }
1391 tcp->flags &= ~TCB_INSYSCALL;
1392 }
1393 }
1394#endif /* SUNOS4 */
1395#ifdef LINUX
1396#if defined (I386)
1397 if (upeek(pid, 4*EAX, &eax) < 0)
1398 return -1;
1399 if (eax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1400 if (debug)
1401 fprintf(stderr, "stray syscall exit: eax = %ld\n", eax);
1402 return 0;
1403 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001404#elif defined (X86_64)
1405 if (upeek(pid, 8*RAX, &rax) < 0)
1406 return -1;
Roland McGrath998fac72004-06-23 01:40:45 +00001407 if (current_personality == 1)
1408 rax = (long int)(int)rax; /* sign extend from 32 bits */
Michal Ludvig0e035502002-09-23 15:41:01 +00001409 if (rax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1410 if (debug)
1411 fprintf(stderr, "stray syscall exit: rax = %ld\n", rax);
1412 return 0;
1413 }
Michal Ludvig10a88d02002-10-07 14:31:00 +00001414#elif defined (S390) || defined (S390X)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001415 if (upeek(pid, PT_GPR2, &gpr2) < 0)
1416 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001417 if (syscall_mode != -ENOSYS)
1418 syscall_mode = tcp->scno;
1419 if (gpr2 != syscall_mode && !(tcp->flags & TCB_INSYSCALL)) {
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001420 if (debug)
1421 fprintf(stderr, "stray syscall exit: gpr2 = %ld\n", gpr2);
1422 return 0;
1423 }
Roland McGrath96dc5142003-01-20 10:23:04 +00001424 else if (((tcp->flags & (TCB_INSYSCALL|TCB_WAITEXECVE))
1425 == (TCB_INSYSCALL|TCB_WAITEXECVE))
1426 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1427 /*
1428 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1429 * flag set for the post-execve SIGTRAP to see and reset.
1430 */
1431 gpr2 = 0;
1432 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001433#elif defined (POWERPC)
1434# define SO_MASK 0x10000000
Roland McGratheb285352003-01-14 09:59:00 +00001435 if (upeek(pid, sizeof(unsigned long)*PT_CCR, &flags) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001436 return -1;
Roland McGratheb285352003-01-14 09:59:00 +00001437 if (upeek(pid, sizeof(unsigned long)*PT_R3, &result) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001438 return -1;
1439 if (flags & SO_MASK)
1440 result = -result;
1441#elif defined (M68K)
1442 if (upeek(pid, 4*PT_D0, &d0) < 0)
1443 return -1;
1444 if (d0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1445 if (debug)
1446 fprintf(stderr, "stray syscall exit: d0 = %ld\n", d0);
1447 return 0;
1448 }
1449#elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001450 /*
1451 * Nothing required
1452 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001453#elif defined (HPPA)
1454 if (upeek(pid, PT_GR28, &r28) < 0)
1455 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001456#elif defined(IA64)
1457 if (upeek(pid, PT_R10, &r10) < 0)
1458 return -1;
1459 if (upeek(pid, PT_R8, &r8) < 0)
1460 return -1;
1461 if (ia32 && r8 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1462 if (debug)
1463 fprintf(stderr, "stray syscall exit: r8 = %ld\n", r8);
1464 return 0;
1465 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001466#endif
1467#endif /* LINUX */
Pavel Machek4dc3b142000-02-01 17:58:41 +00001468 return 1;
1469}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001470
Roland McGratha4d48532005-06-08 20:45:28 +00001471static int
Pavel Machek4dc3b142000-02-01 17:58:41 +00001472get_error(tcp)
1473struct tcb *tcp;
1474{
1475 int u_error = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001476#ifdef LINUX
Michal Ludvig10a88d02002-10-07 14:31:00 +00001477#if defined(S390) || defined(S390X)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001478 if (gpr2 && (unsigned) -gpr2 < nerrnos) {
1479 tcp->u_rval = -1;
1480 u_error = -gpr2;
1481 }
1482 else {
1483 tcp->u_rval = gpr2;
1484 u_error = 0;
1485 }
Michal Ludvig10a88d02002-10-07 14:31:00 +00001486#else /* !S390 && !S390X */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001487#ifdef I386
1488 if (eax < 0 && -eax < nerrnos) {
1489 tcp->u_rval = -1;
1490 u_error = -eax;
1491 }
1492 else {
1493 tcp->u_rval = eax;
1494 u_error = 0;
1495 }
1496#else /* !I386 */
Michal Ludvig0e035502002-09-23 15:41:01 +00001497#ifdef X86_64
1498 if (rax < 0 && -rax < nerrnos) {
1499 tcp->u_rval = -1;
1500 u_error = -rax;
1501 }
1502 else {
1503 tcp->u_rval = rax;
1504 u_error = 0;
1505 }
1506#else
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001507#ifdef IA64
1508 if (ia32) {
1509 int err;
1510
1511 err = (int)r8;
1512 if (err < 0 && -err < nerrnos) {
1513 tcp->u_rval = -1;
1514 u_error = -err;
1515 }
1516 else {
1517 tcp->u_rval = err;
1518 u_error = 0;
1519 }
1520 } else {
1521 if (r10) {
1522 tcp->u_rval = -1;
1523 u_error = r8;
1524 } else {
1525 tcp->u_rval = r8;
1526 u_error = 0;
1527 }
1528 }
1529#else /* !IA64 */
Wichert Akkermanf90da011999-10-31 21:15:38 +00001530#ifdef MIPS
1531 if (a3) {
1532 tcp->u_rval = -1;
1533 u_error = r2;
1534 } else {
1535 tcp->u_rval = r2;
1536 u_error = 0;
1537 }
1538#else
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001539#ifdef POWERPC
Roland McGrath190f8dd2004-01-13 10:13:44 +00001540 if (result && (unsigned long) -result < nerrnos) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001541 tcp->u_rval = -1;
1542 u_error = -result;
1543 }
1544 else {
1545 tcp->u_rval = result;
1546 u_error = 0;
1547 }
1548#else /* !POWERPC */
1549#ifdef M68K
1550 if (d0 && (unsigned) -d0 < nerrnos) {
1551 tcp->u_rval = -1;
1552 u_error = -d0;
1553 }
1554 else {
1555 tcp->u_rval = d0;
1556 u_error = 0;
1557 }
1558#else /* !M68K */
1559#ifdef ARM
Roland McGrath0f87c492003-06-03 23:29:04 +00001560 if (regs.ARM_r0 && (unsigned) -regs.ARM_r0 < nerrnos) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001561 tcp->u_rval = -1;
Roland McGrath0f87c492003-06-03 23:29:04 +00001562 u_error = -regs.ARM_r0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001563 }
1564 else {
Roland McGrath0f87c492003-06-03 23:29:04 +00001565 tcp->u_rval = regs.ARM_r0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001566 u_error = 0;
1567 }
1568#else /* !ARM */
1569#ifdef ALPHA
1570 if (a3) {
1571 tcp->u_rval = -1;
1572 u_error = r0;
1573 }
1574 else {
1575 tcp->u_rval = r0;
1576 u_error = 0;
1577 }
1578#else /* !ALPHA */
1579#ifdef SPARC
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001580 if (regs.r_psr & PSR_C) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001581 tcp->u_rval = -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001582 u_error = regs.r_o0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001583 }
1584 else {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001585 tcp->u_rval = regs.r_o0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001586 u_error = 0;
1587 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001588#else /* !SPARC */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001589#ifdef SPARC64
1590 if (regs.r_tstate & 0x1100000000UL) {
1591 tcp->u_rval = -1;
1592 u_error = regs.r_o0;
1593 }
1594 else {
1595 tcp->u_rval = regs.r_o0;
1596 u_error = 0;
1597 }
1598#else /* !SPARC64 */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001599#ifdef HPPA
1600 if (r28 && (unsigned) -r28 < nerrnos) {
1601 tcp->u_rval = -1;
1602 u_error = -r28;
1603 }
1604 else {
1605 tcp->u_rval = r28;
1606 u_error = 0;
1607 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00001608#else
1609#ifdef SH
1610 /* interpret R0 as return value or error number */
1611 if (r0 && (unsigned) -r0 < nerrnos) {
1612 tcp->u_rval = -1;
1613 u_error = -r0;
1614 }
1615 else {
1616 tcp->u_rval = r0;
1617 u_error = 0;
1618 }
Roland McGrathe1e584b2003-06-02 19:18:58 +00001619#else
Roland McGrathf5a47772003-06-26 22:40:42 +00001620#ifdef SH64
Roland McGrathe1e584b2003-06-02 19:18:58 +00001621 /* interpret result as return value or error number */
1622 if (r9 && (unsigned) -r9 < nerrnos) {
1623 tcp->u_rval = -1;
1624 u_error = -r9;
1625 }
1626 else {
1627 tcp->u_rval = r9;
1628 u_error = 0;
1629 }
Roland McGrathf5a47772003-06-26 22:40:42 +00001630#endif /* SH64 */
Wichert Akkermanccef6372002-05-01 16:39:22 +00001631#endif /* SH */
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001632#endif /* HPPA */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001633#endif /* SPARC */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001634#endif /* SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001635#endif /* ALPHA */
1636#endif /* ARM */
1637#endif /* M68K */
1638#endif /* POWERPC */
Wichert Akkermanf90da011999-10-31 21:15:38 +00001639#endif /* MIPS */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001640#endif /* IA64 */
Michal Ludvig0e035502002-09-23 15:41:01 +00001641#endif /* X86_64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642#endif /* I386 */
Michal Ludvig10a88d02002-10-07 14:31:00 +00001643#endif /* S390 || S390X */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001644#endif /* LINUX */
1645#ifdef SUNOS4
1646 /* get error code from user struct */
1647 if (upeek(pid, uoff(u_error), &u_error) < 0)
1648 return -1;
1649 u_error >>= 24; /* u_error is a char */
1650
1651 /* get system call return value */
1652 if (upeek(pid, uoff(u_rval1), &tcp->u_rval) < 0)
1653 return -1;
1654#endif /* SUNOS4 */
1655#ifdef SVR4
1656#ifdef SPARC
1657 /* Judicious guessing goes a long way. */
1658 if (tcp->status.pr_reg[R_PSR] & 0x100000) {
1659 tcp->u_rval = -1;
1660 u_error = tcp->status.pr_reg[R_O0];
1661 }
1662 else {
1663 tcp->u_rval = tcp->status.pr_reg[R_O0];
1664 u_error = 0;
1665 }
1666#endif /* SPARC */
1667#ifdef I386
1668 /* Wanna know how to kill an hour single-stepping? */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001669 if (tcp->status.PR_REG[EFL] & 0x1) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001670 tcp->u_rval = -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001671 u_error = tcp->status.PR_REG[EAX];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001672 }
1673 else {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001674 tcp->u_rval = tcp->status.PR_REG[EAX];
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001675#ifdef HAVE_LONG_LONG
1676 tcp->u_lrval =
1677 ((unsigned long long) tcp->status.PR_REG[EDX] << 32) +
1678 tcp->status.PR_REG[EAX];
1679#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001680 u_error = 0;
1681 }
1682#endif /* I386 */
Michal Ludvig0e035502002-09-23 15:41:01 +00001683#ifdef X86_64
1684 /* Wanna know how to kill an hour single-stepping? */
1685 if (tcp->status.PR_REG[EFLAGS] & 0x1) {
1686 tcp->u_rval = -1;
1687 u_error = tcp->status.PR_REG[RAX];
1688 }
1689 else {
1690 tcp->u_rval = tcp->status.PR_REG[RAX];
1691 u_error = 0;
1692 }
1693#endif /* X86_64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001694#ifdef MIPS
1695 if (tcp->status.pr_reg[CTX_A3]) {
1696 tcp->u_rval = -1;
1697 u_error = tcp->status.pr_reg[CTX_V0];
1698 }
1699 else {
1700 tcp->u_rval = tcp->status.pr_reg[CTX_V0];
1701 u_error = 0;
1702 }
1703#endif /* MIPS */
1704#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001705#ifdef FREEBSD
1706 if (regs.r_eflags & PSL_C) {
1707 tcp->u_rval = -1;
1708 u_error = regs.r_eax;
1709 } else {
1710 tcp->u_rval = regs.r_eax;
1711 tcp->u_lrval =
1712 ((unsigned long long) regs.r_edx << 32) + regs.r_eax;
1713 u_error = 0;
1714 }
Roland McGrath761b5d72002-12-15 23:58:31 +00001715#endif /* FREEBSD */
Pavel Machek4dc3b142000-02-01 17:58:41 +00001716 tcp->u_error = u_error;
1717 return 1;
1718}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001719
Roland McGrathb69f81b2002-12-21 23:25:18 +00001720int
1721force_result(tcp, error, rval)
1722 struct tcb *tcp;
1723 int error;
1724 long rval;
1725{
1726#ifdef LINUX
1727#if defined(S390) || defined(S390X)
1728 gpr2 = error ? -error : rval;
Roland McGrathb69f81b2002-12-21 23:25:18 +00001729 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_GPR2, gpr2) < 0)
1730 return -1;
1731#else /* !S390 && !S390X */
1732#ifdef I386
1733 eax = error ? -error : rval;
1734 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(EAX * 4), eax) < 0)
1735 return -1;
1736#else /* !I386 */
1737#ifdef X86_64
1738 rax = error ? -error : rval;
Roland McGrath998fac72004-06-23 01:40:45 +00001739 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(RAX * 8), rax) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001740 return -1;
1741#else
1742#ifdef IA64
1743 if (ia32) {
1744 r8 = error ? -error : rval;
1745 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0)
1746 return -1;
1747 }
1748 else {
1749 if (error) {
1750 r8 = error;
1751 r10 = -1;
1752 }
1753 else {
1754 r8 = rval;
1755 r10 = 0;
1756 }
1757 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0 ||
1758 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R10), r10) < 0)
1759 return -1;
1760 }
1761#else /* !IA64 */
1762#ifdef MIPS
1763 if (error) {
1764 r2 = error;
1765 a3 = -1;
1766 }
1767 else {
1768 r2 = rval;
1769 a3 = 0;
1770 }
1771 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1772 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), r2) < 0)
1773 return -1;
1774#else
1775#ifdef POWERPC
Roland McGratheb285352003-01-14 09:59:00 +00001776 if (upeek(tcp->pid, sizeof(unsigned long)*PT_CCR, &flags) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001777 return -1;
1778 if (error) {
1779 flags |= SO_MASK;
1780 result = error;
1781 }
1782 else {
1783 flags &= ~SO_MASK;
1784 result = rval;
1785 }
Roland McGratheb285352003-01-14 09:59:00 +00001786 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_CCR), flags) < 0 ||
1787 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_R3), result) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001788 return -1;
1789#else /* !POWERPC */
1790#ifdef M68K
1791 d0 = error ? -error : rval;
1792 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_D0), d0) < 0)
1793 return -1;
1794#else /* !M68K */
1795#ifdef ARM
Roland McGrath7c051d22003-06-26 22:29:32 +00001796 regs.ARM_r0 = error ? -error : rval;
1797 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*0), regs.ARM_r0) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001798 return -1;
1799#else /* !ARM */
1800#ifdef ALPHA
1801 if (error) {
1802 a3 = -1;
1803 r0 = error;
1804 }
1805 else {
1806 a3 = 0;
1807 r0 = rval;
1808 }
1809 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1810 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R0), r0) < 0)
1811 return -1;
1812#else /* !ALPHA */
1813#ifdef SPARC
1814 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1815 return -1;
1816 if (error) {
1817 regs.r_psr |= PSR_C;
1818 regs.r_o0 = error;
1819 }
1820 else {
1821 regs.r_psr &= ~PSR_C;
1822 regs.r_o0 = rval;
1823 }
1824 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1825 return -1;
1826#else /* !SPARC */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001827#ifdef SPARC64
1828 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1829 return -1;
1830 if (error) {
1831 regs.r_tstate |= 0x1100000000UL;
1832 regs.r_o0 = error;
1833 }
1834 else {
1835 regs.r_tstate &= ~0x1100000000UL;
1836 regs.r_o0 = rval;
1837 }
1838 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1839 return -1;
1840#else /* !SPARC64 */
Roland McGrathb69f81b2002-12-21 23:25:18 +00001841#ifdef HPPA
1842 r28 = error ? -error : rval;
1843 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR28), r28) < 0)
1844 return -1;
1845#else
1846#ifdef SH
1847 r0 = error ? -error : rval;
1848 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*REG_REG0), r0) < 0)
1849 return -1;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001850#else
Roland McGrathf5a47772003-06-26 22:40:42 +00001851#ifdef SH64
Roland McGrathe1e584b2003-06-02 19:18:58 +00001852 r9 = error ? -error : rval;
1853 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_GENERAL(9), r9) < 0)
1854 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001855#endif /* SH64 */
Roland McGrathb69f81b2002-12-21 23:25:18 +00001856#endif /* SH */
1857#endif /* HPPA */
1858#endif /* SPARC */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001859#endif /* SPARC64 */
Roland McGrathb69f81b2002-12-21 23:25:18 +00001860#endif /* ALPHA */
1861#endif /* ARM */
1862#endif /* M68K */
1863#endif /* POWERPC */
1864#endif /* MIPS */
1865#endif /* IA64 */
1866#endif /* X86_64 */
1867#endif /* I386 */
1868#endif /* S390 || S390X */
1869#endif /* LINUX */
1870#ifdef SUNOS4
1871 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_error),
1872 error << 24) < 0 ||
1873 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_rval1), rval) < 0)
1874 return -1;
1875#endif /* SUNOS4 */
1876#ifdef SVR4
1877 /* XXX no clue */
1878 return -1;
1879#endif /* SVR4 */
1880#ifdef FREEBSD
1881 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1882 perror("pread");
1883 return -1;
1884 }
1885 if (error) {
1886 regs.r_eflags |= PSL_C;
1887 regs.r_eax = error;
1888 }
1889 else {
1890 regs.r_eflags &= ~PSL_C;
1891 regs.r_eax = rval;
1892 }
1893 if (pwrite(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1894 perror("pwrite");
1895 return -1;
1896 }
1897#endif /* FREEBSD */
1898
1899 /* All branches reach here on success (only). */
1900 tcp->u_error = error;
1901 tcp->u_rval = rval;
1902 return 0;
1903}
1904
Roland McGratha4d48532005-06-08 20:45:28 +00001905static int
1906syscall_enter(tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001907struct tcb *tcp;
1908{
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001909#ifndef USE_PROCFS
Pavel Machek4dc3b142000-02-01 17:58:41 +00001910 int pid = tcp->pid;
Roland McGrath761b5d72002-12-15 23:58:31 +00001911#endif /* !USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001912#ifdef LINUX
Michal Ludvig10a88d02002-10-07 14:31:00 +00001913#if defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001914 {
1915 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001916 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1917 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00001918 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001919 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001920 for (i = 0; i < tcp->u_nargs; i++) {
Michal Ludvig10a88d02002-10-07 14:31:00 +00001921 if (upeek(pid,i==0 ? PT_ORIGGPR2:PT_GPR2+i*sizeof(long), &tcp->u_arg[i]) < 0)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00001922 return -1;
1923 }
1924 }
1925#elif defined (ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001926 {
1927 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001928 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1929 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00001930 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001931 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001932 for (i = 0; i < tcp->u_nargs; i++) {
Wichert Akkermanb859bea1999-04-18 22:50:50 +00001933 /* WTA: if scno is out-of-bounds this will bomb. Add range-check
1934 * for scno somewhere above here!
1935 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001936 if (upeek(pid, REG_A0+i, &tcp->u_arg[i]) < 0)
1937 return -1;
1938 }
1939 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001940#elif defined (IA64)
1941 {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001942 if (!ia32) {
1943 unsigned long *out0, *rbs_end, cfm, sof, sol, i;
1944 /* be backwards compatible with kernel < 2.4.4... */
1945# ifndef PT_RBS_END
1946# define PT_RBS_END PT_AR_BSP
1947# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001948
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001949 if (upeek(pid, PT_RBS_END, (long *) &rbs_end) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001950 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001951 if (upeek(pid, PT_CFM, (long *) &cfm) < 0)
1952 return -1;
1953
1954 sof = (cfm >> 0) & 0x7f;
1955 sol = (cfm >> 7) & 0x7f;
1956 out0 = ia64_rse_skip_regs(rbs_end, -sof + sol);
1957
1958 if (tcp->scno >= 0 && tcp->scno < nsyscalls
1959 && sysent[tcp->scno].nargs != -1)
1960 tcp->u_nargs = sysent[tcp->scno].nargs;
1961 else
1962 tcp->u_nargs = MAX_ARGS;
1963 for (i = 0; i < tcp->u_nargs; ++i) {
1964 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1965 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1966 return -1;
1967 }
1968 } else {
1969 int i;
1970
1971 if (/* EBX = out0 */
1972 upeek(pid, PT_R11, (long *) &tcp->u_arg[0]) < 0
1973 /* ECX = out1 */
1974 || upeek(pid, PT_R9, (long *) &tcp->u_arg[1]) < 0
1975 /* EDX = out2 */
1976 || upeek(pid, PT_R10, (long *) &tcp->u_arg[2]) < 0
1977 /* ESI = out3 */
1978 || upeek(pid, PT_R14, (long *) &tcp->u_arg[3]) < 0
1979 /* EDI = out4 */
1980 || upeek(pid, PT_R15, (long *) &tcp->u_arg[4]) < 0
1981 /* EBP = out5 */
1982 || upeek(pid, PT_R13, (long *) &tcp->u_arg[5]) < 0)
1983 return -1;
1984
1985 for (i = 0; i < 6; ++i)
1986 /* truncate away IVE sign-extension */
1987 tcp->u_arg[i] &= 0xffffffff;
1988
1989 if (tcp->scno >= 0 && tcp->scno < nsyscalls
1990 && sysent[tcp->scno].nargs != -1)
1991 tcp->u_nargs = sysent[tcp->scno].nargs;
1992 else
1993 tcp->u_nargs = 5;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001994 }
1995 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001996#elif defined (MIPS)
1997 {
1998 long sp;
1999 int i, nargs;
2000
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002001 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2002 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002003 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002004 nargs = tcp->u_nargs = MAX_ARGS;
Wichert Akkermanf90da011999-10-31 21:15:38 +00002005 if(nargs > 4) {
2006 if(upeek(pid, REG_SP, &sp) < 0)
2007 return -1;
2008 for(i = 0; i < 4; i++) {
2009 if (upeek(pid, REG_A0 + i, &tcp->u_arg[i])<0)
2010 return -1;
2011 }
2012 umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]),
2013 (char *)(tcp->u_arg + 4));
2014 } else {
2015 for(i = 0; i < nargs; i++) {
2016 if (upeek(pid, REG_A0 + i, &tcp->u_arg[i]) < 0)
2017 return -1;
2018 }
2019 }
2020 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002021#elif defined (POWERPC)
Roland McGrath761b5d72002-12-15 23:58:31 +00002022#ifndef PT_ORIG_R3
2023#define PT_ORIG_R3 34
2024#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002025 {
2026 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002027 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2028 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002029 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002030 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002031 for (i = 0; i < tcp->u_nargs; i++) {
Roland McGratheb285352003-01-14 09:59:00 +00002032 if (upeek(pid, (i==0) ?
2033 (sizeof(unsigned long)*PT_ORIG_R3) :
2034 ((i+PT_R3)*sizeof(unsigned long)),
2035 &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002036 return -1;
2037 }
2038 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002039#elif defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002040 {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002041 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002042
2043 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2044 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002045 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002046 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002047 for (i = 0; i < tcp->u_nargs; i++)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002048 tcp->u_arg[i] = *((&regs.r_o0) + i);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002049 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002050#elif defined (HPPA)
2051 {
2052 int i;
2053
2054 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2055 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002056 else
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002057 tcp->u_nargs = MAX_ARGS;
2058 for (i = 0; i < tcp->u_nargs; i++) {
2059 if (upeek(pid, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
2060 return -1;
2061 }
2062 }
Roland McGrath0f87c492003-06-03 23:29:04 +00002063#elif defined(ARM)
2064 {
2065 int i;
2066
2067 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2068 tcp->u_nargs = sysent[tcp->scno].nargs;
2069 else
2070 tcp->u_nargs = MAX_ARGS;
2071 for (i = 0; i < tcp->u_nargs; i++)
2072 tcp->u_arg[i] = regs.uregs[i];
2073 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00002074#elif defined(SH)
2075 {
Roland McGrath761b5d72002-12-15 23:58:31 +00002076 int i;
Wichert Akkermanccef6372002-05-01 16:39:22 +00002077 static int syscall_regs[] = {
2078 REG_REG0+4, REG_REG0+5, REG_REG0+6, REG_REG0+7,
2079 REG_REG0, REG_REG0+1, REG_REG0+2
2080 };
2081
2082 tcp->u_nargs = sysent[tcp->scno].nargs;
2083 for (i = 0; i < tcp->u_nargs; i++) {
2084 if (upeek(pid, 4*syscall_regs[i], &tcp->u_arg[i]) < 0)
2085 return -1;
2086 }
2087 }
Roland McGrathf5a47772003-06-26 22:40:42 +00002088#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00002089 {
2090 int i;
2091 /* Registers used by SH5 Linux system calls for parameters */
2092 static int syscall_regs[] = { 2, 3, 4, 5, 6, 7 };
2093
2094 /*
2095 * TODO: should also check that the number of arguments encoded
2096 * in the trap number matches the number strace expects.
2097 */
2098 /*
2099 assert(sysent[tcp->scno].nargs <
2100 sizeof(syscall_regs)/sizeof(syscall_regs[0]));
2101 */
2102
2103 tcp->u_nargs = sysent[tcp->scno].nargs;
2104 for (i = 0; i < tcp->u_nargs; i++) {
2105 if (upeek(pid, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
2106 return -1;
2107 }
2108 }
2109
Michal Ludvig0e035502002-09-23 15:41:01 +00002110#elif defined(X86_64)
2111 {
2112 int i;
2113 static int argreg[SUPPORTED_PERSONALITIES][MAX_ARGS] = {
2114 {RDI,RSI,RDX,R10,R8,R9}, /* x86-64 ABI */
Roland McGrath5a9c6ad2005-02-02 03:06:52 +00002115 {RBX,RCX,RDX,RSI,RDI,RBP} /* i386 ABI */
Michal Ludvig0e035502002-09-23 15:41:01 +00002116 };
Roland McGrath761b5d72002-12-15 23:58:31 +00002117
Michal Ludvig0e035502002-09-23 15:41:01 +00002118 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2119 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002120 else
Michal Ludvig0e035502002-09-23 15:41:01 +00002121 tcp->u_nargs = MAX_ARGS;
2122 for (i = 0; i < tcp->u_nargs; i++) {
2123 if (upeek(pid, argreg[current_personality][i]*8, &tcp->u_arg[i]) < 0)
2124 return -1;
2125 }
2126 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00002127#else /* Other architecture (like i386) (32bits specific) */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002128 {
2129 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002130 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2131 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002132 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002133 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002134 for (i = 0; i < tcp->u_nargs; i++) {
2135 if (upeek(pid, i*4, &tcp->u_arg[i]) < 0)
2136 return -1;
2137 }
2138 }
Roland McGrath761b5d72002-12-15 23:58:31 +00002139#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002140#endif /* LINUX */
2141#ifdef SUNOS4
2142 {
2143 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002144 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2145 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002146 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002147 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002148 for (i = 0; i < tcp->u_nargs; i++) {
2149 struct user *u;
2150
2151 if (upeek(pid, uoff(u_arg[0]) +
2152 (i*sizeof(u->u_arg[0])), &tcp->u_arg[i]) < 0)
2153 return -1;
2154 }
2155 }
2156#endif /* SUNOS4 */
2157#ifdef SVR4
2158#ifdef MIPS
2159 /*
2160 * SGI is broken: even though it has pr_sysarg, it doesn't
2161 * set them on system call entry. Get a clue.
2162 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002163 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002164 tcp->u_nargs = sysent[tcp->scno].nargs;
2165 else
2166 tcp->u_nargs = tcp->status.pr_nsysarg;
2167 if (tcp->u_nargs > 4) {
2168 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2169 4*sizeof(tcp->u_arg[0]));
2170 umoven(tcp, tcp->status.pr_reg[CTX_SP] + 16,
2171 (tcp->u_nargs - 4)*sizeof(tcp->u_arg[0]), (char *) (tcp->u_arg + 4));
2172 }
2173 else {
2174 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2175 tcp->u_nargs*sizeof(tcp->u_arg[0]));
2176 }
John Hughes25299712001-03-06 10:10:06 +00002177#elif UNIXWARE >= 2
2178 /*
2179 * Like SGI, UnixWare doesn't set pr_sysarg until system call exit
2180 */
2181 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2182 tcp->u_nargs = sysent[tcp->scno].nargs;
2183 else
2184 tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;
2185 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
2186 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2187#elif defined (HAVE_PR_SYSCALL)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002188 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002189 tcp->u_nargs = sysent[tcp->scno].nargs;
2190 else
2191 tcp->u_nargs = tcp->status.pr_nsysarg;
2192 {
2193 int i;
2194 for (i = 0; i < tcp->u_nargs; i++)
2195 tcp->u_arg[i] = tcp->status.pr_sysarg[i];
2196 }
John Hughes25299712001-03-06 10:10:06 +00002197#elif defined (I386)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002198 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002199 tcp->u_nargs = sysent[tcp->scno].nargs;
2200 else
2201 tcp->u_nargs = 5;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002202 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002203 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
John Hughes25299712001-03-06 10:10:06 +00002204#else
2205 I DONT KNOW WHAT TO DO
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002206#endif /* !HAVE_PR_SYSCALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002207#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002208#ifdef FREEBSD
2209 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2210 sysent[tcp->scno].nargs > tcp->status.val)
2211 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002212 else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002213 tcp->u_nargs = tcp->status.val;
2214 if (tcp->u_nargs < 0)
2215 tcp->u_nargs = 0;
2216 if (tcp->u_nargs > MAX_ARGS)
2217 tcp->u_nargs = MAX_ARGS;
2218 switch(regs.r_eax) {
2219 case SYS___syscall:
2220 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2221 regs.r_esp + sizeof(int) + sizeof(quad_t));
2222 break;
2223 case SYS_syscall:
2224 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2225 regs.r_esp + 2 * sizeof(int));
2226 break;
2227 default:
2228 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2229 regs.r_esp + sizeof(int));
2230 break;
2231 }
2232#endif /* FREEBSD */
Pavel Machek4dc3b142000-02-01 17:58:41 +00002233 return 1;
2234}
2235
2236int
Dmitry V. Levin7d61ff12006-12-21 21:15:04 +00002237trace_syscall(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002238{
2239 int sys_res;
2240 struct timeval tv;
2241 int res;
2242
2243 /* Measure the exit time as early as possible to avoid errors. */
2244 if (dtime && (tcp->flags & TCB_INSYSCALL))
2245 gettimeofday(&tv, NULL);
2246
2247 res = get_scno(tcp);
2248 if (res != 1)
2249 return res;
2250
2251 res = syscall_fixup(tcp);
2252 if (res != 1)
2253 return res;
2254
2255 if (tcp->flags & TCB_INSYSCALL) {
2256 long u_error;
2257 res = get_error(tcp);
2258 if (res != 1)
2259 return res;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002260
2261 internal_syscall(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002262 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2263 !(qual_flags[tcp->scno] & QUAL_TRACE)) {
Pavel Machek4dc3b142000-02-01 17:58:41 +00002264 tcp->flags &= ~TCB_INSYSCALL;
2265 return 0;
2266 }
2267
2268 if (tcp->flags & TCB_REPRINT) {
2269 printleader(tcp);
2270 tprintf("<... ");
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002271 if (tcp->scno >= nsyscalls || tcp->scno < 0)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002272 tprintf("syscall_%lu", tcp->scno);
2273 else
2274 tprintf("%s", sysent[tcp->scno].sys_name);
2275 tprintf(" resumed> ");
2276 }
2277
Dmitry V. Levin7d61ff12006-12-21 21:15:04 +00002278 if (cflag)
2279 return count_syscall(tcp, &tv);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002280
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002281 if (tcp->scno >= nsyscalls || tcp->scno < 0
Pavel Machek4dc3b142000-02-01 17:58:41 +00002282 || (qual_flags[tcp->scno] & QUAL_RAW))
2283 sys_res = printargs(tcp);
Michal Ludvig17f8fb32002-11-06 13:17:21 +00002284 else {
2285 if (not_failing_only && tcp->u_error)
Roland McGrath761b5d72002-12-15 23:58:31 +00002286 return 0; /* ignore failed syscalls */
Pavel Machek4dc3b142000-02-01 17:58:41 +00002287 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
Roland McGrath761b5d72002-12-15 23:58:31 +00002288 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002289 u_error = tcp->u_error;
2290 tprintf(") ");
2291 tabto(acolumn);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002292 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2293 qual_flags[tcp->scno] & QUAL_RAW) {
Pavel Machek4dc3b142000-02-01 17:58:41 +00002294 if (u_error)
2295 tprintf("= -1 (errno %ld)", u_error);
2296 else
2297 tprintf("= %#lx", tcp->u_rval);
2298 }
2299 else if (!(sys_res & RVAL_NONE) && u_error) {
2300 switch (u_error) {
2301#ifdef LINUX
2302 case ERESTARTSYS:
2303 tprintf("= ? ERESTARTSYS (To be restarted)");
2304 break;
2305 case ERESTARTNOINTR:
2306 tprintf("= ? ERESTARTNOINTR (To be restarted)");
2307 break;
2308 case ERESTARTNOHAND:
2309 tprintf("= ? ERESTARTNOHAND (To be restarted)");
2310 break;
Roland McGrath9c555e72003-07-09 09:47:59 +00002311 case ERESTART_RESTARTBLOCK:
2312 tprintf("= ? ERESTART_RESTARTBLOCK (To be restarted)");
2313 break;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002314#endif /* LINUX */
2315 default:
2316 tprintf("= -1 ");
Wichert Akkerman4527dae2002-03-31 19:03:29 +00002317 if (u_error < 0)
2318 tprintf("E??? (errno %ld)", u_error);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002319 else if (u_error < nerrnos)
Roland McGrath761b5d72002-12-15 23:58:31 +00002320 tprintf("%s (%s)", errnoent[u_error],
2321 strerror(u_error));
Pavel Machek4dc3b142000-02-01 17:58:41 +00002322 else
Roland McGrath761b5d72002-12-15 23:58:31 +00002323 tprintf("ERRNO_%ld (%s)", u_error,
2324 strerror(u_error));
Pavel Machek4dc3b142000-02-01 17:58:41 +00002325 break;
2326 }
2327 }
2328 else {
2329 if (sys_res & RVAL_NONE)
2330 tprintf("= ?");
2331 else {
2332 switch (sys_res & RVAL_MASK) {
2333 case RVAL_HEX:
2334 tprintf("= %#lx", tcp->u_rval);
2335 break;
2336 case RVAL_OCTAL:
2337 tprintf("= %#lo", tcp->u_rval);
2338 break;
2339 case RVAL_UDECIMAL:
2340 tprintf("= %lu", tcp->u_rval);
2341 break;
2342 case RVAL_DECIMAL:
2343 tprintf("= %ld", tcp->u_rval);
2344 break;
Wichert Akkerman16a03d22000-08-10 02:14:04 +00002345#ifdef HAVE_LONG_LONG
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002346 case RVAL_LHEX:
2347 tprintf("= %#llx", tcp->u_lrval);
Wichert Akkerman16a03d22000-08-10 02:14:04 +00002348 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002349 case RVAL_LOCTAL:
2350 tprintf("= %#llo", tcp->u_lrval);
2351 break;
2352 case RVAL_LUDECIMAL:
2353 tprintf("= %llu", tcp->u_lrval);
2354 break;
2355 case RVAL_LDECIMAL:
2356 tprintf("= %lld", tcp->u_lrval);
2357 break;
Wichert Akkerman16a03d22000-08-10 02:14:04 +00002358#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00002359 default:
2360 fprintf(stderr,
2361 "invalid rval format\n");
2362 break;
2363 }
2364 }
2365 if ((sys_res & RVAL_STR) && tcp->auxstr)
2366 tprintf(" (%s)", tcp->auxstr);
2367 }
2368 if (dtime) {
2369 tv_sub(&tv, &tv, &tcp->etime);
2370 tprintf(" <%ld.%06ld>",
2371 (long) tv.tv_sec, (long) tv.tv_usec);
2372 }
2373 printtrailer(tcp);
2374
2375 dumpio(tcp);
2376 if (fflush(tcp->outf) == EOF)
2377 return -1;
2378 tcp->flags &= ~TCB_INSYSCALL;
2379 return 0;
2380 }
2381
2382 /* Entering system call */
2383 res = syscall_enter(tcp);
2384 if (res != 1)
2385 return res;
2386
Roland McGrath17352792005-06-07 23:21:26 +00002387 switch (known_scno(tcp)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002388#ifdef LINUX
Roland McGrath17352792005-06-07 23:21:26 +00002389#if !defined (ALPHA) && !defined(SPARC) && !defined(SPARC64) && !defined(MIPS) && !defined(HPPA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002390 case SYS_socketcall:
2391 decode_subcall(tcp, SYS_socket_subcall,
2392 SYS_socket_nsubcalls, deref_style);
2393 break;
2394 case SYS_ipc:
2395 decode_subcall(tcp, SYS_ipc_subcall,
2396 SYS_ipc_nsubcalls, shift_style);
2397 break;
Roland McGrath17352792005-06-07 23:21:26 +00002398#endif /* !ALPHA && !MIPS && !SPARC && !SPARC64 && !HPPA */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002399#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002400 case SYS_socketcall:
2401 sparc_socket_decode (tcp);
2402 break;
2403#endif
2404#endif /* LINUX */
2405#ifdef SVR4
2406#ifdef SYS_pgrpsys_subcall
2407 case SYS_pgrpsys:
2408 decode_subcall(tcp, SYS_pgrpsys_subcall,
2409 SYS_pgrpsys_nsubcalls, shift_style);
2410 break;
2411#endif /* SYS_pgrpsys_subcall */
2412#ifdef SYS_sigcall_subcall
2413 case SYS_sigcall:
2414 decode_subcall(tcp, SYS_sigcall_subcall,
2415 SYS_sigcall_nsubcalls, mask_style);
2416 break;
2417#endif /* SYS_sigcall_subcall */
2418 case SYS_msgsys:
2419 decode_subcall(tcp, SYS_msgsys_subcall,
2420 SYS_msgsys_nsubcalls, shift_style);
2421 break;
2422 case SYS_shmsys:
2423 decode_subcall(tcp, SYS_shmsys_subcall,
2424 SYS_shmsys_nsubcalls, shift_style);
2425 break;
2426 case SYS_semsys:
2427 decode_subcall(tcp, SYS_semsys_subcall,
2428 SYS_semsys_nsubcalls, shift_style);
2429 break;
2430#if 0 /* broken */
2431 case SYS_utssys:
2432 decode_subcall(tcp, SYS_utssys_subcall,
2433 SYS_utssys_nsubcalls, shift_style);
2434 break;
2435#endif
2436 case SYS_sysfs:
2437 decode_subcall(tcp, SYS_sysfs_subcall,
2438 SYS_sysfs_nsubcalls, shift_style);
2439 break;
2440 case SYS_spcall:
2441 decode_subcall(tcp, SYS_spcall_subcall,
2442 SYS_spcall_nsubcalls, shift_style);
2443 break;
2444#ifdef SYS_context_subcall
2445 case SYS_context:
2446 decode_subcall(tcp, SYS_context_subcall,
2447 SYS_context_nsubcalls, shift_style);
2448 break;
2449#endif /* SYS_context_subcall */
Wichert Akkerman8829a551999-06-11 13:18:40 +00002450#ifdef SYS_door_subcall
2451 case SYS_door:
2452 decode_subcall(tcp, SYS_door_subcall,
2453 SYS_door_nsubcalls, door_style);
2454 break;
2455#endif /* SYS_door_subcall */
John Hughesbdf48f52001-03-06 15:08:09 +00002456#ifdef SYS_kaio_subcall
2457 case SYS_kaio:
2458 decode_subcall(tcp, SYS_kaio_subcall,
2459 SYS_kaio_nsubcalls, shift_style);
2460 break;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002461#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002462#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002463#ifdef FREEBSD
2464 case SYS_msgsys:
2465 case SYS_shmsys:
2466 case SYS_semsys:
2467 decode_subcall(tcp, 0, 0, table_style);
2468 break;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002469#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002470#ifdef SUNOS4
2471 case SYS_semsys:
2472 decode_subcall(tcp, SYS_semsys_subcall,
2473 SYS_semsys_nsubcalls, shift_style);
2474 break;
2475 case SYS_msgsys:
2476 decode_subcall(tcp, SYS_msgsys_subcall,
2477 SYS_msgsys_nsubcalls, shift_style);
2478 break;
2479 case SYS_shmsys:
2480 decode_subcall(tcp, SYS_shmsys_subcall,
2481 SYS_shmsys_nsubcalls, shift_style);
2482 break;
2483#endif
2484 }
2485
2486 internal_syscall(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002487 if (tcp->scno >=0 && tcp->scno < nsyscalls && !(qual_flags[tcp->scno] & QUAL_TRACE)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002488 tcp->flags |= TCB_INSYSCALL;
2489 return 0;
2490 }
2491
2492 if (cflag) {
2493 gettimeofday(&tcp->etime, NULL);
2494 tcp->flags |= TCB_INSYSCALL;
2495 return 0;
2496 }
2497
2498 printleader(tcp);
2499 tcp->flags &= ~TCB_REPRINT;
2500 tcp_last = tcp;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002501 if (tcp->scno >= nsyscalls || tcp->scno < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002502 tprintf("syscall_%lu(", tcp->scno);
2503 else
2504 tprintf("%s(", sysent[tcp->scno].sys_name);
Roland McGrath761b5d72002-12-15 23:58:31 +00002505 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002506 ((qual_flags[tcp->scno] & QUAL_RAW) && tcp->scno != SYS_exit))
2507 sys_res = printargs(tcp);
2508 else
2509 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2510 if (fflush(tcp->outf) == EOF)
2511 return -1;
2512 tcp->flags |= TCB_INSYSCALL;
2513 /* Measure the entrance time as late as possible to avoid errors. */
2514 if (dtime)
2515 gettimeofday(&tcp->etime, NULL);
2516 return sys_res;
2517}
2518
2519int
2520printargs(tcp)
2521struct tcb *tcp;
2522{
2523 if (entering(tcp)) {
2524 int i;
2525
2526 for (i = 0; i < tcp->u_nargs; i++)
2527 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
2528 }
2529 return 0;
2530}
2531
2532long
2533getrval2(tcp)
2534struct tcb *tcp;
2535{
2536 long val = -1;
2537
2538#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002539#if defined (SPARC) || defined (SPARC64)
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002540 struct regs regs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002541 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
2542 return -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002543 val = regs.r_o1;
Roland McGrath6b1d43e2003-03-31 01:05:01 +00002544#elif defined(SH)
2545 if (upeek(tcp->pid, 4*(REG_REG0+1), &val) < 0)
2546 return -1;
Roland McGrathb4ce1762004-03-01 20:30:48 +00002547#elif defined(IA64)
2548 if (upeek(tcp->pid, PT_R9, &val) < 0)
2549 return -1;
Roland McGrath920e6bb2005-03-15 02:15:20 +00002550#endif /* SPARC || SPARC64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002551#endif /* LINUX */
2552
2553#ifdef SUNOS4
2554 if (upeek(tcp->pid, uoff(u_rval2), &val) < 0)
2555 return -1;
2556#endif /* SUNOS4 */
2557
2558#ifdef SVR4
2559#ifdef SPARC
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002560 val = tcp->status.PR_REG[R_O1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002561#endif /* SPARC */
2562#ifdef I386
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002563 val = tcp->status.PR_REG[EDX];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002564#endif /* I386 */
Michal Ludvig0e035502002-09-23 15:41:01 +00002565#ifdef X86_64
2566 val = tcp->status.PR_REG[RDX];
2567#endif /* X86_64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002568#ifdef MIPS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002569 val = tcp->status.PR_REG[CTX_V1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002570#endif /* MIPS */
2571#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002572#ifdef FREEBSD
2573 struct reg regs;
2574 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
2575 val = regs.r_edx;
Roland McGrath761b5d72002-12-15 23:58:31 +00002576#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002577 return val;
2578}
2579
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +00002580#ifdef SUNOS4
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002581/*
2582 * Apparently, indirect system calls have already be converted by ptrace(2),
2583 * so if you see "indir" this program has gone astray.
2584 */
2585int
2586sys_indir(tcp)
2587struct tcb *tcp;
2588{
2589 int i, scno, nargs;
2590
2591 if (entering(tcp)) {
2592 if ((scno = tcp->u_arg[0]) > nsyscalls) {
2593 fprintf(stderr, "Bogus syscall: %u\n", scno);
2594 return 0;
2595 }
2596 nargs = sysent[scno].nargs;
2597 tprintf("%s", sysent[scno].sys_name);
2598 for (i = 0; i < nargs; i++)
2599 tprintf(", %#lx", tcp->u_arg[i+1]);
2600 }
2601 return 0;
2602}
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +00002603#endif /* SUNOS4 */