blob: 39135f768cda16ea40ebd73e881bb04e3f422006 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $Id$
34 */
35
36#include "defs.h"
37
38#include <signal.h>
39#include <time.h>
40#include <errno.h>
41#include <sys/user.h>
42#include <sys/syscall.h>
43#include <sys/param.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000044
Wichert Akkerman15dea971999-10-06 13:06:34 +000045#ifdef HAVE_SYS_REG_H
Roland McGratheb9e2e82009-06-02 16:49:22 -070046#include <sys/reg.h>
47#ifndef PTRACE_PEEKUSR
48# define PTRACE_PEEKUSR PTRACE_PEEKUSER
49#endif
Wichert Akkermanfaf72222000-02-19 23:59:03 +000050#elif defined(HAVE_LINUX_PTRACE_H)
Roland McGratheb9e2e82009-06-02 16:49:22 -070051#undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000052# ifdef HAVE_STRUCT_IA64_FPREG
53# define ia64_fpreg XXX_ia64_fpreg
54# endif
55# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
56# define pt_all_user_regs XXX_pt_all_user_regs
57# endif
Roland McGratheb9e2e82009-06-02 16:49:22 -070058#include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000059# undef ia64_fpreg
60# undef pt_all_user_regs
Wichert Akkerman15dea971999-10-06 13:06:34 +000061#endif
62
Roland McGrath6d1a65c2004-07-12 07:44:08 +000063#if defined (LINUX) && defined (SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +000064# undef PTRACE_GETREGS
65# define PTRACE_GETREGS PTRACE_GETREGS64
66# undef PTRACE_SETREGS
67# define PTRACE_SETREGS PTRACE_SETREGS64
68#endif /* LINUX && SPARC64 */
69
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000070#if defined(LINUX) && defined(IA64)
71# include <asm/ptrace_offsets.h>
72# include <asm/rse.h>
73#endif
74
Pavel Machekd8ae7e32000-02-01 17:17:25 +000075#define NR_SYSCALL_BASE 0
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000076#ifdef LINUX
77#ifndef ERESTARTSYS
78#define ERESTARTSYS 512
79#endif
80#ifndef ERESTARTNOINTR
81#define ERESTARTNOINTR 513
82#endif
83#ifndef ERESTARTNOHAND
84#define ERESTARTNOHAND 514 /* restart if no handler.. */
85#endif
86#ifndef ENOIOCTLCMD
87#define ENOIOCTLCMD 515 /* No ioctl command */
88#endif
Roland McGrath9c555e72003-07-09 09:47:59 +000089#ifndef ERESTART_RESTARTBLOCK
90#define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
91#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000092#ifndef NSIG
93#define NSIG 32
94#endif
95#ifdef ARM
96#undef NSIG
97#define NSIG 32
Pavel Machekd8ae7e32000-02-01 17:17:25 +000098#undef NR_SYSCALL_BASE
99#define NR_SYSCALL_BASE __NR_SYSCALL_BASE
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000100#endif
101#endif /* LINUX */
102
103#include "syscall.h"
104
105/* Define these shorthand notations to simplify the syscallent files. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000106#define TD TRACE_DESC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000107#define TF TRACE_FILE
108#define TI TRACE_IPC
109#define TN TRACE_NETWORK
110#define TP TRACE_PROCESS
111#define TS TRACE_SIGNAL
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000112#define NF SYSCALL_NEVER_FAILS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000113
Roland McGrathee36ce12004-09-04 03:53:10 +0000114static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000115#include "syscallent.h"
116};
Roland McGrathee36ce12004-09-04 03:53:10 +0000117static const int nsyscalls0 = sizeof sysent0 / sizeof sysent0[0];
Roland McGrath138c6a32006-01-12 09:50:49 +0000118int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000119
120#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000121static const struct sysent sysent1[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122#include "syscallent1.h"
123};
Roland McGrathee36ce12004-09-04 03:53:10 +0000124static const int nsyscalls1 = sizeof sysent1 / sizeof sysent1[0];
Roland McGrath138c6a32006-01-12 09:50:49 +0000125int qual_flags1[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000126#endif /* SUPPORTED_PERSONALITIES >= 2 */
127
128#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000129static const struct sysent sysent2[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130#include "syscallent2.h"
131};
Roland McGrathee36ce12004-09-04 03:53:10 +0000132static const int nsyscalls2 = sizeof sysent2 / sizeof sysent2[0];
Roland McGrath138c6a32006-01-12 09:50:49 +0000133int qual_flags2[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000134#endif /* SUPPORTED_PERSONALITIES >= 3 */
135
Roland McGrathee36ce12004-09-04 03:53:10 +0000136const struct sysent *sysent;
Roland McGrath138c6a32006-01-12 09:50:49 +0000137int *qual_flags;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000138int nsyscalls;
139
140/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000141#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142#undef TF
143#undef TI
144#undef TN
145#undef TP
146#undef TS
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000147#undef NF
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000148
Roland McGrathee36ce12004-09-04 03:53:10 +0000149static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000150#include "errnoent.h"
151};
Roland McGrathee36ce12004-09-04 03:53:10 +0000152static const int nerrnos0 = sizeof errnoent0 / sizeof errnoent0[0];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000153
154#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000155static const char *const errnoent1[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000156#include "errnoent1.h"
157};
Roland McGrathee36ce12004-09-04 03:53:10 +0000158static const int nerrnos1 = sizeof errnoent1 / sizeof errnoent1[0];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000159#endif /* SUPPORTED_PERSONALITIES >= 2 */
160
161#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000162static const char *const errnoent2[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000163#include "errnoent2.h"
164};
Roland McGrathee36ce12004-09-04 03:53:10 +0000165static const int nerrnos2 = sizeof errnoent2 / sizeof errnoent2[0];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000166#endif /* SUPPORTED_PERSONALITIES >= 3 */
167
Roland McGrathee36ce12004-09-04 03:53:10 +0000168const char *const *errnoent;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000169int nerrnos;
170
171int current_personality;
172
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000173#ifndef PERSONALITY0_WORDSIZE
174# define PERSONALITY0_WORDSIZE sizeof(long)
175#endif
176const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
177 PERSONALITY0_WORDSIZE,
178#if SUPPORTED_PERSONALITIES > 1
179 PERSONALITY1_WORDSIZE,
180#endif
181#if SUPPORTED_PERSONALITIES > 2
182 PERSONALITY2_WORDSIZE,
183#endif
184};;
185
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000186int
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000187set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000188{
189 switch (personality) {
190 case 0:
191 errnoent = errnoent0;
192 nerrnos = nerrnos0;
193 sysent = sysent0;
194 nsyscalls = nsyscalls0;
195 ioctlent = ioctlent0;
196 nioctlents = nioctlents0;
197 signalent = signalent0;
198 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000199 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000200 break;
201
202#if SUPPORTED_PERSONALITIES >= 2
203 case 1:
204 errnoent = errnoent1;
205 nerrnos = nerrnos1;
206 sysent = sysent1;
207 nsyscalls = nsyscalls1;
208 ioctlent = ioctlent1;
209 nioctlents = nioctlents1;
210 signalent = signalent1;
211 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000212 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000213 break;
214#endif /* SUPPORTED_PERSONALITIES >= 2 */
215
216#if SUPPORTED_PERSONALITIES >= 3
217 case 2:
218 errnoent = errnoent2;
219 nerrnos = nerrnos2;
220 sysent = sysent2;
221 nsyscalls = nsyscalls2;
222 ioctlent = ioctlent2;
223 nioctlents = nioctlents2;
224 signalent = signalent2;
225 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000226 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000227 break;
228#endif /* SUPPORTED_PERSONALITIES >= 3 */
229
230 default:
231 return -1;
232 }
233
234 current_personality = personality;
235 return 0;
236}
237
Roland McGrathe10e62a2004-09-04 04:20:43 +0000238
Roland McGrath9797ceb2002-12-30 10:23:00 +0000239static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000240
Roland McGrathe10e62a2004-09-04 04:20:43 +0000241static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000242 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000243 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000244 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000245 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000246} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000247 { QUAL_TRACE, "trace", qual_syscall, "system call" },
248 { QUAL_TRACE, "t", qual_syscall, "system call" },
249 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
250 { QUAL_ABBREV, "a", qual_syscall, "system call" },
251 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
252 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
253 { QUAL_RAW, "raw", qual_syscall, "system call" },
254 { QUAL_RAW, "x", qual_syscall, "system call" },
255 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
256 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
257 { QUAL_SIGNAL, "s", qual_signal, "signal" },
258 { QUAL_FAULT, "fault", qual_fault, "fault" },
259 { QUAL_FAULT, "faults", qual_fault, "fault" },
260 { QUAL_FAULT, "m", qual_fault, "fault" },
261 { QUAL_READ, "read", qual_desc, "descriptor" },
262 { QUAL_READ, "reads", qual_desc, "descriptor" },
263 { QUAL_READ, "r", qual_desc, "descriptor" },
264 { QUAL_WRITE, "write", qual_desc, "descriptor" },
265 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
266 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000267 { 0, NULL, NULL, NULL },
268};
269
Roland McGrath9797ceb2002-12-30 10:23:00 +0000270static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000271qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000272{
Roland McGrath138c6a32006-01-12 09:50:49 +0000273 if (pers == 0 || pers < 0) {
274 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000275 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000276 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000277 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000278 }
279
280#if SUPPORTED_PERSONALITIES >= 2
281 if (pers == 1 || pers < 0) {
282 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000283 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000284 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000285 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000286 }
287#endif /* SUPPORTED_PERSONALITIES >= 2 */
288
289#if SUPPORTED_PERSONALITIES >= 3
290 if (pers == 2 || pers < 0) {
291 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000292 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000293 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000294 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000295 }
296#endif /* SUPPORTED_PERSONALITIES >= 3 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000297}
298
299static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000300qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000301{
302 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000303 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000304
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000305 if (isdigit((unsigned char)*s)) {
306 int i = atoi(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000307 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000308 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000309 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000310 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000311 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000312 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000313 if (strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000314 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000315 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000316 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000317
318#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000319 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000320 if (strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000321 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000322 rc = 0;
323 }
324#endif /* SUPPORTED_PERSONALITIES >= 2 */
325
326#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000327 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000328 if (strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000329 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000330 rc = 0;
331 }
332#endif /* SUPPORTED_PERSONALITIES >= 3 */
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000333
Roland McGrathfe6b3522005-02-02 04:40:11 +0000334 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000335}
336
337static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000338qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000339{
340 int i;
341 char buf[32];
342
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000343 if (isdigit((unsigned char)*s)) {
344 int signo = atoi(s);
345 if (signo < 0 || signo >= MAX_QUALS)
346 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000347 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000348 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000349 }
Roland McGrathd62b6712004-03-02 06:52:01 +0000350 if (strlen(s) >= sizeof buf)
Roland McGrathfe6b3522005-02-02 04:40:11 +0000351 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000352 strcpy(buf, s);
353 s = buf;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000354 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000355 s += 3;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000356 for (i = 0; i <= NSIG; i++)
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000357 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000358 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000359 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000360 }
Roland McGrath76421df2005-02-02 03:51:18 +0000361 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000362}
363
364static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000365qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000366{
367 return -1;
368}
369
370static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000371qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000372{
Roland McGrath48a035f2006-01-12 09:45:56 +0000373 if (isdigit((unsigned char)*s)) {
Roland McGrathfe6b3522005-02-02 04:40:11 +0000374 int desc = atoi(s);
375 if (desc < 0 || desc >= MAX_QUALS)
376 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000377 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000378 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000379 }
380 return -1;
381}
382
383static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000384lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000385{
386 if (strcmp(s, "file") == 0)
387 return TRACE_FILE;
388 if (strcmp(s, "ipc") == 0)
389 return TRACE_IPC;
390 if (strcmp(s, "network") == 0)
391 return TRACE_NETWORK;
392 if (strcmp(s, "process") == 0)
393 return TRACE_PROCESS;
394 if (strcmp(s, "signal") == 0)
395 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000396 if (strcmp(s, "desc") == 0)
397 return TRACE_DESC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000398 return -1;
399}
400
401void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000402qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000403{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000404 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000405 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000406 char *copy;
407 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000408 int i, n;
409
410 opt = &qual_options[0];
411 for (i = 0; (p = qual_options[i].option_name); i++) {
412 n = strlen(p);
413 if (strncmp(s, p, n) == 0 && s[n] == '=') {
414 opt = &qual_options[i];
415 s += n + 1;
416 break;
417 }
418 }
419 not = 0;
420 if (*s == '!') {
421 not = 1;
422 s++;
423 }
424 if (strcmp(s, "none") == 0) {
425 not = 1 - not;
426 s = "all";
427 }
428 if (strcmp(s, "all") == 0) {
429 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000430 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000431 }
432 return;
433 }
434 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000435 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000436 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000437 if (!(copy = strdup(s))) {
438 fprintf(stderr, "out of memory\n");
439 exit(1);
440 }
441 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000442 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000443 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000444 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000445 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000446
447#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000448 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000449 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000450 qualify_one(i, opt->bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000451#endif /* SUPPORTED_PERSONALITIES >= 2 */
452
453#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000454 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000455 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000456 qualify_one(i, opt->bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000457#endif /* SUPPORTED_PERSONALITIES >= 3 */
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000458
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000459 continue;
460 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000461 if (opt->qualify(p, opt->bitflag, not)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000462 fprintf(stderr, "strace: invalid %s `%s'\n",
463 opt->argument_name, p);
464 exit(1);
465 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000466 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000467 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000468 return;
469}
470
471static void
472dumpio(tcp)
473struct tcb *tcp;
474{
475 if (syserror(tcp))
476 return;
477 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
478 return;
Roland McGrath17352792005-06-07 23:21:26 +0000479 switch (known_scno(tcp)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000480 case SYS_read:
Roland McGrathaa510622004-08-31 07:47:45 +0000481#ifdef SYS_pread64
482 case SYS_pread64:
483#endif
484#if defined SYS_pread && SYS_pread64 != SYS_pread
485 case SYS_pread:
486#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000487#ifdef SYS_recv
488 case SYS_recv:
Roland McGrath17352792005-06-07 23:21:26 +0000489#elif defined SYS_sub_recv
490 case SYS_sub_recv:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000491#endif
492#ifdef SYS_recvfrom
493 case SYS_recvfrom:
Roland McGrath17352792005-06-07 23:21:26 +0000494#elif defined SYS_sub_recvfrom
495 case SYS_sub_recvfrom:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000496#endif
497 if (qual_flags[tcp->u_arg[0]] & QUAL_READ)
498 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
499 break;
500 case SYS_write:
Roland McGrathaa510622004-08-31 07:47:45 +0000501#ifdef SYS_pwrite64
502 case SYS_pwrite64:
503#endif
504#if defined SYS_pwrite && SYS_pwrite64 != SYS_pwrite
505 case SYS_pwrite:
506#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000507#ifdef SYS_send
508 case SYS_send:
Roland McGrath17352792005-06-07 23:21:26 +0000509#elif defined SYS_sub_send
510 case SYS_sub_send:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000511#endif
512#ifdef SYS_sendto
513 case SYS_sendto:
Roland McGrath17352792005-06-07 23:21:26 +0000514#elif defined SYS_sub_sendto
515 case SYS_sub_sendto:
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000516#endif
517 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE)
518 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
519 break;
John Hughes1d08dcf2001-07-10 13:48:44 +0000520#ifdef SYS_readv
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000521 case SYS_readv:
522 if (qual_flags[tcp->u_arg[0]] & QUAL_READ)
523 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
524 break;
John Hughes1d08dcf2001-07-10 13:48:44 +0000525#endif
526#ifdef SYS_writev
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000527 case SYS_writev:
528 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE)
529 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
530 break;
John Hughes1d08dcf2001-07-10 13:48:44 +0000531#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000532 }
533}
534
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000535#ifndef FREEBSD
Wichert Akkerman8829a551999-06-11 13:18:40 +0000536enum subcall_style { shift_style, deref_style, mask_style, door_style };
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000537#else /* FREEBSD */
538enum subcall_style { shift_style, deref_style, mask_style, door_style, table_style };
539
540struct subcall {
541 int call;
542 int nsubcalls;
543 int subcalls[5];
544};
545
Roland McGratha4d48532005-06-08 20:45:28 +0000546static const struct subcall subcalls_table[] = {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000547 { SYS_shmsys, 5, { SYS_shmat, SYS_shmctl, SYS_shmdt, SYS_shmget, SYS_shmctl } },
John Hughes61eeb552001-03-06 15:51:53 +0000548#ifdef SYS_semconfig
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000549 { SYS_semsys, 4, { SYS___semctl, SYS_semget, SYS_semop, SYS_semconfig } },
John Hughes61eeb552001-03-06 15:51:53 +0000550#else
551 { SYS_semsys, 3, { SYS___semctl, SYS_semget, SYS_semop } },
552#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000553 { SYS_msgsys, 4, { SYS_msgctl, SYS_msgget, SYS_msgsnd, SYS_msgrcv } },
554};
555#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000556
Denys Vlasenko8ba1cd72008-12-30 17:50:46 +0000557#if !(defined(LINUX) && ( defined(ALPHA) || defined(MIPS) || defined(__ARM_EABI__) ))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000558
Roland McGratha4d48532005-06-08 20:45:28 +0000559static void
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000560decode_subcall(tcp, subcall, nsubcalls, style)
561struct tcb *tcp;
562int subcall;
563int nsubcalls;
564enum subcall_style style;
565{
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000566 unsigned long addr, mask;
Michal Ludvig10a88d02002-10-07 14:31:00 +0000567 int i;
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000568 int size = personality_wordsize[current_personality];
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000569
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000570 switch (style) {
571 case shift_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000572 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
573 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000574 tcp->scno = subcall + tcp->u_arg[0];
575 if (sysent[tcp->scno].nargs != -1)
576 tcp->u_nargs = sysent[tcp->scno].nargs;
577 else
578 tcp->u_nargs--;
579 for (i = 0; i < tcp->u_nargs; i++)
580 tcp->u_arg[i] = tcp->u_arg[i + 1];
581 break;
582 case deref_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000583 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
584 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000585 tcp->scno = subcall + tcp->u_arg[0];
586 addr = tcp->u_arg[1];
587 for (i = 0; i < sysent[tcp->scno].nargs; i++) {
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000588 if (size == sizeof(int)) {
589 unsigned int arg;
590 if (umove(tcp, addr, &arg) < 0)
591 arg = 0;
592 tcp->u_arg[i] = arg;
593 }
594 else if (size == sizeof(long)) {
595 unsigned long arg;
596 if (umove(tcp, addr, &arg) < 0)
597 arg = 0;
598 tcp->u_arg[i] = arg;
599 }
600 else
601 abort();
602 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000603 }
604 tcp->u_nargs = sysent[tcp->scno].nargs;
605 break;
606 case mask_style:
607 mask = (tcp->u_arg[0] >> 8) & 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000608 for (i = 0; mask; i++)
609 mask >>= 1;
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000610 if (i >= nsubcalls)
611 return;
612 tcp->u_arg[0] &= 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000613 tcp->scno = subcall + i;
614 if (sysent[tcp->scno].nargs != -1)
615 tcp->u_nargs = sysent[tcp->scno].nargs;
616 break;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000617 case door_style:
618 /*
619 * Oh, yuck. The call code is the *sixth* argument.
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000620 * (don't you mean the *last* argument? - JH)
Wichert Akkerman8829a551999-06-11 13:18:40 +0000621 */
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000622 if (tcp->u_arg[5] < 0 || tcp->u_arg[5] >= nsubcalls)
623 return;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000624 tcp->scno = subcall + tcp->u_arg[5];
625 if (sysent[tcp->scno].nargs != -1)
626 tcp->u_nargs = sysent[tcp->scno].nargs;
627 else
628 tcp->u_nargs--;
629 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000630#ifdef FREEBSD
631 case table_style:
632 for (i = 0; i < sizeof(subcalls_table) / sizeof(struct subcall); i++)
633 if (subcalls_table[i].call == tcp->scno) break;
634 if (i < sizeof(subcalls_table) / sizeof(struct subcall) &&
635 tcp->u_arg[0] >= 0 && tcp->u_arg[0] < subcalls_table[i].nsubcalls) {
636 tcp->scno = subcalls_table[i].subcalls[tcp->u_arg[0]];
637 for (i = 0; i < tcp->u_nargs; i++)
638 tcp->u_arg[i] = tcp->u_arg[i + 1];
639 }
640 break;
641#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000642 }
643}
644#endif
645
646struct tcb *tcp_last = NULL;
647
648static int
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000649internal_syscall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000650{
651 /*
652 * We must always trace a few critical system calls in order to
653 * correctly support following forks in the presence of tracing
654 * qualifiers.
655 */
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000656 int (*func)();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000657
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000658 if (tcp->scno < 0 || tcp->scno >= nsyscalls)
659 return 0;
660
661 func = sysent[tcp->scno].sys_func;
662
663 if (sys_exit == func)
664 return internal_exit(tcp);
665
666 if ( sys_fork == func
667#if defined(FREEBSD) || defined(LINUX) || defined(SUNOS4)
668 || sys_vfork == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000669#endif
Dmitry V. Levin257e1572009-12-26 17:55:24 +0000670#ifdef LINUX
671 || sys_clone == func
672#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000673#if UNIXWARE > 2
674 || sys_rfork == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000675#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000676 )
677 return internal_fork(tcp);
678
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000679 if ( sys_execve == func
680#if defined(SPARC) || defined(SPARC64) || defined(SUNOS4)
681 || sys_execv == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000682#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000683#if UNIXWARE > 2
684 || sys_rexecve == func
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000685#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000686 )
687 return internal_exec(tcp);
688
689 if ( sys_waitpid == func
690 || sys_wait4 == func
691#if defined(SVR4) || defined(FREEBSD) || defined(SUNOS4)
692 || sys_wait == func
Roland McGrath923f7502003-01-09 06:53:27 +0000693#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000694#ifdef ALPHA
695 || sys_osf_wait4 == func
Roland McGrath08267b82004-02-20 22:56:43 +0000696#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000697 )
698 return internal_wait(tcp, 2);
699
700#if defined(LINUX) || defined(SVR4)
701 if (sys_waitid == func)
702 return internal_wait(tcp, 3);
703#endif
704
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000705 return 0;
706}
707
Wichert Akkermanc7926982000-04-10 22:22:31 +0000708
709#ifdef LINUX
710#if defined (I386)
711 static long eax;
712#elif defined (IA64)
713 long r8, r10, psr;
714 long ia32 = 0;
715#elif defined (POWERPC)
716 static long result,flags;
717#elif defined (M68K)
Andreas Schwabffca9e32010-05-28 20:53:14 +0200718 static long d0;
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000719#elif defined(BFIN)
720 static long r0;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000721#elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +0000722 static struct pt_regs regs;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000723#elif defined (ALPHA)
724 static long r0;
725 static long a3;
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000726#elif defined(AVR32)
727 static struct pt_regs regs;
Roland McGrath6d1a65c2004-07-12 07:44:08 +0000728#elif defined (SPARC) || defined (SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -0400729 static struct pt_regs regs;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000730 static unsigned long trap;
Roland McGrath542c2c62008-05-20 01:11:56 +0000731#elif defined(LINUX_MIPSN32)
732 static long long a3;
733 static long long r2;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000734#elif defined(MIPS)
735 static long a3;
736 static long r2;
Michal Ludvig10a88d02002-10-07 14:31:00 +0000737#elif defined(S390) || defined(S390X)
Wichert Akkermanc7926982000-04-10 22:22:31 +0000738 static long gpr2;
739 static long pc;
Michal Ludvig882eda82002-11-11 12:50:47 +0000740 static long syscall_mode;
Wichert Akkermanc1652e22001-03-27 12:17:16 +0000741#elif defined(HPPA)
742 static long r28;
Wichert Akkermanccef6372002-05-01 16:39:22 +0000743#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000744 static long r0;
Roland McGrathf5a47772003-06-26 22:40:42 +0000745#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000746 static long r9;
Michal Ludvig0e035502002-09-23 15:41:01 +0000747#elif defined(X86_64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000748 static long rax;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000749#elif defined(CRISV10) || defined(CRISV32)
750 static long r10;
Edgar E. Iglesias939caba2010-07-06 14:21:07 +0200751#elif defined(MICROBLAZE)
752 static long r3;
Roland McGrath761b5d72002-12-15 23:58:31 +0000753#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000754#endif /* LINUX */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000755#ifdef FREEBSD
756 struct reg regs;
Roland McGrath761b5d72002-12-15 23:58:31 +0000757#endif /* FREEBSD */
Wichert Akkermanc7926982000-04-10 22:22:31 +0000758
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000759int
Denys Vlasenkofb036672009-01-23 16:30:26 +0000760get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000761{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000762 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000763
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000764#ifdef LINUX
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000765# if defined(S390) || defined(S390X)
Roland McGrath96dc5142003-01-20 10:23:04 +0000766 if (tcp->flags & TCB_WAITEXECVE) {
767 /*
768 * When the execve system call completes successfully, the
769 * new process still has -ENOSYS (old style) or __NR_execve
770 * (new style) in gpr2. We cannot recover the scno again
771 * by disassembly, because the image that executed the
772 * syscall is gone now. Fortunately, we don't want it. We
773 * leave the flag set so that syscall_fixup can fake the
774 * result.
775 */
776 if (tcp->flags & TCB_INSYSCALL)
777 return 1;
778 /*
779 * This is the SIGTRAP after execve. We cannot try to read
780 * the system call here either.
781 */
782 tcp->flags &= ~TCB_WAITEXECVE;
783 return 0;
784 }
Roland McGrath2f924ca2003-06-26 22:23:28 +0000785
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000786 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Roland McGrath2f924ca2003-06-26 22:23:28 +0000787 return -1;
788
789 if (syscall_mode != -ENOSYS) {
790 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000791 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000792 */
793 scno = syscall_mode;
794 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000795 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000796 * Old style of "passing" the scno via the SVC instruction.
797 */
798
799 long opcode, offset_reg, tmp;
800 void * svc_addr;
801 int gpr_offset[16] = {PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
802 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
803 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
804 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15};
Roland McGrath761b5d72002-12-15 23:58:31 +0000805
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000806 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000807 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000808 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000809 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000810 if (errno) {
811 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000812 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000813 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000814
815 /*
816 * We have to check if the SVC got executed directly or via an
817 * EXECUTE instruction. In case of EXECUTE it is necessary to do
818 * instruction decoding to derive the system call number.
819 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
820 * so that this doesn't work if a SVC opcode is part of an EXECUTE
821 * opcode. Since there is no way to find out the opcode size this
822 * is the best we can do...
823 */
824
825 if ((opcode & 0xff00) == 0x0a00) {
826 /* SVC opcode */
827 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000828 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000829 else {
830 /* SVC got executed by EXECUTE instruction */
831
832 /*
833 * Do instruction decoding of EXECUTE. If you really want to
834 * understand this, read the Principles of Operations.
835 */
836 svc_addr = (void *) (opcode & 0xfff);
837
838 tmp = 0;
839 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000840 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000841 return -1;
842 svc_addr += tmp;
843
844 tmp = 0;
845 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000846 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000847 return -1;
848 svc_addr += tmp;
849
Denys Vlasenkofb036672009-01-23 16:30:26 +0000850 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000851 if (errno)
852 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000853# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000854 scno >>= 48;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000855# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000856 scno >>= 16;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000857# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000858 tmp = 0;
859 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000860 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000861 return -1;
862
863 scno = (scno | tmp) & 0xff;
864 }
865 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000866# elif defined (POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000867 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000868 return -1;
869 if (!(tcp->flags & TCB_INSYSCALL)) {
870 /* Check if we return from execve. */
871 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
872 tcp->flags &= ~TCB_WAITEXECVE;
873 return 0;
874 }
875 }
Andreas Schwabd69fa492010-07-12 21:39:57 +0200876
877# ifdef POWERPC64
878 if (!(tcp->flags & TCB_INSYSCALL)) {
879 static int currpers = -1;
880 long val;
881 int pid = tcp->pid;
882
883 /* Check for 64/32 bit mode. */
884 if (upeek(tcp, sizeof (unsigned long)*PT_MSR, &val) < 0)
885 return -1;
886 /* SF is bit 0 of MSR */
887 if (val < 0)
888 currpers = 0;
889 else
890 currpers = 1;
891 if (currpers != current_personality) {
892 static const char *const names[] = {"64 bit", "32 bit"};
893 set_personality(currpers);
Dmitry V. Levinbdafa1a2010-12-02 23:38:13 +0000894 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
Andreas Schwabd69fa492010-07-12 21:39:57 +0200895 pid, names[current_personality]);
896 }
897 }
898# endif
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000899# elif defined(AVR32)
900 /*
901 * Read complete register set in one go.
902 */
903 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
904 return -1;
905
906 /*
907 * We only need to grab the syscall number on syscall entry.
908 */
909 if (!(tcp->flags & TCB_INSYSCALL)) {
910 scno = regs.r8;
911
912 /* Check if we return from execve. */
913 if (tcp->flags & TCB_WAITEXECVE) {
914 tcp->flags &= ~TCB_WAITEXECVE;
915 return 0;
916 }
917 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000918# elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000919 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000920 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000921# elif defined (I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000922 if (upeek(tcp, 4*ORIG_EAX, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000923 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000924# elif defined (X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000925 if (upeek(tcp, 8*ORIG_RAX, &scno) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +0000926 return -1;
927
Roland McGrath761b5d72002-12-15 23:58:31 +0000928 if (!(tcp->flags & TCB_INSYSCALL)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000929 static int currpers = -1;
Michal Ludvig0e035502002-09-23 15:41:01 +0000930 long val;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000931 int pid = tcp->pid;
Michal Ludvig0e035502002-09-23 15:41:01 +0000932
933 /* Check CS register value. On x86-64 linux it is:
934 * 0x33 for long mode (64 bit)
935 * 0x23 for compatibility mode (32 bit)
Roland McGrath761b5d72002-12-15 23:58:31 +0000936 * It takes only one ptrace and thus doesn't need
Michal Ludvig0e035502002-09-23 15:41:01 +0000937 * to be cached.
938 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000939 if (upeek(tcp, 8*CS, &val) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +0000940 return -1;
Denys Vlasenko8236f252009-01-02 18:10:08 +0000941 switch (val) {
Michal Ludvig0e035502002-09-23 15:41:01 +0000942 case 0x23: currpers = 1; break;
943 case 0x33: currpers = 0; break;
944 default:
945 fprintf(stderr, "Unknown value CS=0x%02X while "
946 "detecting personality of process "
947 "PID=%d\n", (int)val, pid);
948 currpers = current_personality;
949 break;
950 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000951# if 0
Michal Ludvig0e035502002-09-23 15:41:01 +0000952 /* This version analyzes the opcode of a syscall instruction.
953 * (int 0x80 on i386 vs. syscall on x86-64)
954 * It works, but is too complicated.
955 */
956 unsigned long val, rip, i;
957
Denys Vlasenko8236f252009-01-02 18:10:08 +0000958 if (upeek(tcp, 8*RIP, &rip) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +0000959 perror("upeek(RIP)");
Roland McGrath761b5d72002-12-15 23:58:31 +0000960
Michal Ludvig0e035502002-09-23 15:41:01 +0000961 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
Denys Vlasenko8236f252009-01-02 18:10:08 +0000962 rip -= 2;
Michal Ludvig0e035502002-09-23 15:41:01 +0000963 errno = 0;
964
Denys Vlasenko8236f252009-01-02 18:10:08 +0000965 call = ptrace(PTRACE_PEEKTEXT, pid, (char *)rip, (char *)0);
Roland McGrath761b5d72002-12-15 23:58:31 +0000966 if (errno)
Dmitry V. Levinbdafa1a2010-12-02 23:38:13 +0000967 fprintf(stderr, "ptrace_peektext failed: %s\n",
Michal Ludvig0e035502002-09-23 15:41:01 +0000968 strerror(errno));
Denys Vlasenko8236f252009-01-02 18:10:08 +0000969 switch (call & 0xffff) {
Michal Ludvig0e035502002-09-23 15:41:01 +0000970 /* x86-64: syscall = 0x0f 0x05 */
971 case 0x050f: currpers = 0; break;
972 /* i386: int 0x80 = 0xcd 0x80 */
973 case 0x80cd: currpers = 1; break;
974 default:
975 currpers = current_personality;
Roland McGrath761b5d72002-12-15 23:58:31 +0000976 fprintf(stderr,
Michal Ludvig0e035502002-09-23 15:41:01 +0000977 "Unknown syscall opcode (0x%04X) while "
978 "detecting personality of process "
979 "PID=%d\n", (int)call, pid);
980 break;
981 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000982# endif
Denys Vlasenko8236f252009-01-02 18:10:08 +0000983 if (currpers != current_personality) {
984 static const char *const names[] = {"64 bit", "32 bit"};
Michal Ludvig0e035502002-09-23 15:41:01 +0000985 set_personality(currpers);
Dmitry V. Levinbdafa1a2010-12-02 23:38:13 +0000986 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
Michal Ludvig0e035502002-09-23 15:41:01 +0000987 pid, names[current_personality]);
988 }
Roland McGrath761b5d72002-12-15 23:58:31 +0000989 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000990# elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000991# define IA64_PSR_IS ((long)1 << 34)
Roland McGratheb9e2e82009-06-02 16:49:22 -0700992 if (upeek (tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000993 ia32 = (psr & IA64_PSR_IS) != 0;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000994 if (!(tcp->flags & TCB_INSYSCALL)) {
995 if (ia32) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000996 if (upeek(tcp, PT_R1, &scno) < 0) /* orig eax */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000997 return -1;
998 } else {
Roland McGratheb9e2e82009-06-02 16:49:22 -0700999 if (upeek (tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001000 return -1;
1001 }
Roland McGrathba954762003-03-05 06:29:06 +00001002 /* Check if we return from execve. */
1003 if (tcp->flags & TCB_WAITEXECVE) {
1004 tcp->flags &= ~TCB_WAITEXECVE;
1005 return 0;
1006 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001007 } else {
1008 /* syscall in progress */
Roland McGratheb9e2e82009-06-02 16:49:22 -07001009 if (upeek (tcp, PT_R8, &r8) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001010 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07001011 if (upeek (tcp, PT_R10, &r10) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001012 return -1;
1013 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001014# elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001015 /*
1016 * Read complete register set in one go.
1017 */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001018 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +00001019 return -1;
1020
1021 /*
1022 * We only need to grab the syscall number on syscall entry.
1023 */
1024 if (regs.ARM_ip == 0) {
Roland McGrath9bc63402007-11-01 21:42:18 +00001025 if (!(tcp->flags & TCB_INSYSCALL)) {
1026 /* Check if we return from execve. */
1027 if (tcp->flags & TCB_WAITEXECVE) {
1028 tcp->flags &= ~TCB_WAITEXECVE;
1029 return 0;
1030 }
1031 }
1032
Roland McGrath0f87c492003-06-03 23:29:04 +00001033 /*
1034 * Note: we only deal with only 32-bit CPUs here.
1035 */
1036 if (regs.ARM_cpsr & 0x20) {
1037 /*
1038 * Get the Thumb-mode system call number
1039 */
1040 scno = regs.ARM_r7;
1041 } else {
1042 /*
1043 * Get the ARM-mode system call number
1044 */
1045 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +00001046 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +00001047 if (errno)
1048 return -1;
1049
1050 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
1051 tcp->flags &= ~TCB_WAITEXECVE;
1052 return 0;
1053 }
1054
Roland McGrathf691bd22006-04-25 07:34:41 +00001055 /* Handle the EABI syscall convention. We do not
1056 bother converting structures between the two
1057 ABIs, but basic functionality should work even
1058 if strace and the traced program have different
1059 ABIs. */
1060 if (scno == 0xef000000) {
1061 scno = regs.ARM_r7;
1062 } else {
1063 if ((scno & 0x0ff00000) != 0x0f900000) {
1064 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1065 scno);
1066 return -1;
1067 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001068
Roland McGrathf691bd22006-04-25 07:34:41 +00001069 /*
1070 * Fixup the syscall number
1071 */
1072 scno &= 0x000fffff;
1073 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001074 }
Roland McGrath56703312008-05-20 01:35:55 +00001075 if (scno & 0x0f0000) {
1076 /*
1077 * Handle ARM specific syscall
1078 */
1079 set_personality(1);
1080 scno &= 0x0000ffff;
1081 } else
1082 set_personality(0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001083
1084 if (tcp->flags & TCB_INSYSCALL) {
1085 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1086 tcp->flags &= ~TCB_INSYSCALL;
1087 }
1088 } else {
1089 if (!(tcp->flags & TCB_INSYSCALL)) {
1090 fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
1091 tcp->flags |= TCB_INSYSCALL;
1092 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001093 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001094# elif defined (M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001095 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001096 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001097# elif defined (LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001098 unsigned long long regs[38];
1099
Roland McGratheb9e2e82009-06-02 16:49:22 -07001100 if (ptrace (PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001101 return -1;
1102 a3 = regs[REG_A3];
1103 r2 = regs[REG_V0];
1104
1105 if(!(tcp->flags & TCB_INSYSCALL)) {
1106 scno = r2;
1107
1108 /* Check if we return from execve. */
1109 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1110 tcp->flags &= ~TCB_WAITEXECVE;
1111 return 0;
1112 }
1113
1114 if (scno < 0 || scno > nsyscalls) {
1115 if(a3 == 0 || a3 == -1) {
1116 if(debug)
1117 fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
1118 return 0;
1119 }
1120 }
1121 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001122# elif defined (MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001123 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001124 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001125 if(!(tcp->flags & TCB_INSYSCALL)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001126 if (upeek(tcp, REG_V0, &scno) < 0)
1127 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001128
Roland McGrath542c2c62008-05-20 01:11:56 +00001129 /* Check if we return from execve. */
1130 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1131 tcp->flags &= ~TCB_WAITEXECVE;
1132 return 0;
1133 }
1134
Wichert Akkermanf90da011999-10-31 21:15:38 +00001135 if (scno < 0 || scno > nsyscalls) {
1136 if(a3 == 0 || a3 == -1) {
1137 if(debug)
1138 fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
1139 return 0;
1140 }
1141 }
1142 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001143 if (upeek(tcp, REG_V0, &r2) < 0)
1144 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001145 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001146# elif defined (ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001147 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001148 return -1;
1149
1150 if (!(tcp->flags & TCB_INSYSCALL)) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001151 if (upeek(tcp, REG_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001152 return -1;
1153
1154 /* Check if we return from execve. */
1155 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1156 tcp->flags &= ~TCB_WAITEXECVE;
1157 return 0;
1158 }
1159
1160 /*
1161 * Do some sanity checks to figure out if it's
1162 * really a syscall entry
1163 */
1164 if (scno < 0 || scno > nsyscalls) {
1165 if (a3 == 0 || a3 == -1) {
1166 if (debug)
1167 fprintf (stderr, "stray syscall exit: r0 = %ld\n", scno);
1168 return 0;
1169 }
1170 }
1171 }
1172 else {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001173 if (upeek(tcp, REG_R0, &r0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001174 return -1;
1175 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001176# elif defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001177 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001178 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001179 return -1;
1180
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001181 /* If we are entering, then disassemble the syscall trap. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001182 if (!(tcp->flags & TCB_INSYSCALL)) {
1183 /* Retrieve the syscall trap instruction. */
1184 errno = 0;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001185# if defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001186 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001187 trap >>= 32;
Mike Frysinger8566c502009-10-12 11:05:14 -04001188# else
1189 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001190# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001191 if (errno)
1192 return -1;
1193
1194 /* Disassemble the trap to see what personality to use. */
1195 switch (trap) {
1196 case 0x91d02010:
1197 /* Linux/SPARC syscall trap. */
1198 set_personality(0);
1199 break;
Wichert Akkermandacfb6e1999-06-03 14:21:07 +00001200 case 0x91d0206d:
1201 /* Linux/SPARC64 syscall trap. */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001202 set_personality(2);
1203 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001204 case 0x91d02000:
1205 /* SunOS syscall trap. (pers 1) */
1206 fprintf(stderr,"syscall: SunOS no support\n");
1207 return -1;
1208 case 0x91d02008:
1209 /* Solaris 2.x syscall trap. (per 2) */
1210 set_personality(1);
Roland McGrath761b5d72002-12-15 23:58:31 +00001211 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001212 case 0x91d02009:
1213 /* NetBSD/FreeBSD syscall trap. */
1214 fprintf(stderr,"syscall: NetBSD/FreeBSD not supported\n");
1215 return -1;
1216 case 0x91d02027:
1217 /* Solaris 2.x gettimeofday */
1218 set_personality(1);
1219 break;
1220 default:
1221 /* Unknown syscall trap. */
1222 if(tcp->flags & TCB_WAITEXECVE) {
1223 tcp->flags &= ~TCB_WAITEXECVE;
1224 return 0;
1225 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001226# if defined (SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001227 fprintf(stderr,"syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001228# else
Mike Frysinger8566c502009-10-12 11:05:14 -04001229 fprintf(stderr,"syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001230# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001231 return -1;
1232 }
1233
1234 /* Extract the system call number from the registers. */
1235 if (trap == 0x91d02027)
1236 scno = 156;
1237 else
Mike Frysinger8566c502009-10-12 11:05:14 -04001238 scno = regs.u_regs[U_REG_G1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001239 if (scno == 0) {
Mike Frysinger8566c502009-10-12 11:05:14 -04001240 scno = regs.u_regs[U_REG_O0];
1241 memmove (&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001242 }
1243 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001244# elif defined(HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001245 if (upeek(tcp, PT_GR20, &scno) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001246 return -1;
1247 if (!(tcp->flags & TCB_INSYSCALL)) {
1248 /* Check if we return from execve. */
1249 if ((tcp->flags & TCB_WAITEXECVE)) {
1250 tcp->flags &= ~TCB_WAITEXECVE;
1251 return 0;
1252 }
1253 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001254# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001255 /*
1256 * In the new syscall ABI, the system call number is in R3.
1257 */
1258 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1259 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001260
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001261 if (scno < 0) {
1262 /* Odd as it may seem, a glibc bug has been known to cause
1263 glibc to issue bogus negative syscall numbers. So for
1264 our purposes, make strace print what it *should* have been */
1265 long correct_scno = (scno & 0xff);
1266 if (debug)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001267 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001268 "Detected glibc bug: bogus system call"
1269 " number = %ld, correcting to %ld\n",
1270 scno,
1271 correct_scno);
1272 scno = correct_scno;
1273 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00001274
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001275 if (!(tcp->flags & TCB_INSYSCALL)) {
1276 /* Check if we return from execve. */
1277 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1278 tcp->flags &= ~TCB_WAITEXECVE;
1279 return 0;
1280 }
1281 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001282# elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001283 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001284 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001285 scno &= 0xFFFF;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001286
1287 if (!(tcp->flags & TCB_INSYSCALL)) {
1288 /* Check if we return from execve. */
1289 if (tcp->flags & TCB_WAITEXECVE) {
1290 tcp->flags &= ~TCB_WAITEXECVE;
1291 return 0;
1292 }
1293 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001294# elif defined(CRISV10) || defined(CRISV32)
1295 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1296 return -1;
Chris Metcalfc8c66982009-12-28 10:00:15 -05001297# elif defined(TILE)
1298 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1299 return -1;
1300
1301 if (!(tcp->flags & TCB_INSYSCALL)) {
1302 /* Check if we return from execve. */
1303 if (tcp->flags & TCB_WAITEXECVE) {
1304 tcp->flags &= ~TCB_WAITEXECVE;
1305 return 0;
1306 }
1307 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001308# elif defined(MICROBLAZE)
1309 if (upeek(tcp, 0, &scno) < 0)
1310 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001311# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001312#endif /* LINUX */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001313
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001314#ifdef SUNOS4
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001315 if (upeek(tcp, uoff(u_arg[7]), &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001316 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001317#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001318 /* new syscall ABI returns result in R0 */
1319 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1320 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001321#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001322 /* ABI defines result returned in r9 */
1323 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1324 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001325#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001326
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001327#ifdef USE_PROCFS
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001328# ifdef HAVE_PR_SYSCALL
John Hughes25299712001-03-06 10:10:06 +00001329 scno = tcp->status.PR_SYSCALL;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001330# else
1331# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001332 scno = tcp->status.PR_WHAT;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001333# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001334 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001335 perror("pread");
1336 return -1;
1337 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001338 switch (regs.r_eax) {
1339 case SYS_syscall:
1340 case SYS___syscall:
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001341 pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int));
1342 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001343 default:
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001344 scno = regs.r_eax;
1345 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001346 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001347# endif /* FREEBSD */
1348# endif /* !HAVE_PR_SYSCALL */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001349#endif /* USE_PROCFS */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001350
Wichert Akkerman5ae21ea2000-05-01 01:53:59 +00001351 if (!(tcp->flags & TCB_INSYSCALL))
1352 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001353 return 1;
1354}
1355
Pavel Machek4dc3b142000-02-01 17:58:41 +00001356
Roland McGrath17352792005-06-07 23:21:26 +00001357long
1358known_scno(tcp)
1359struct tcb *tcp;
1360{
1361 long scno = tcp->scno;
1362 if (scno >= 0 && scno < nsyscalls && sysent[scno].native_scno != 0)
1363 scno = sysent[scno].native_scno;
1364 else
1365 scno += NR_SYSCALL_BASE;
1366 return scno;
1367}
1368
Roland McGratheb9e2e82009-06-02 16:49:22 -07001369/* Called in trace_syscall() at each syscall entry and exit.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001370 * Returns:
Roland McGratheb9e2e82009-06-02 16:49:22 -07001371 * 0: "ignore this syscall", bail out of trace_syscall() silently.
1372 * 1: ok, continue in trace_syscall().
1373 * other: error, trace_syscall() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001374 * ("????" etc) and bail out.
1375 */
Roland McGratha4d48532005-06-08 20:45:28 +00001376static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001377syscall_fixup(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001378{
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001379#ifdef USE_PROCFS
Roland McGrath17352792005-06-07 23:21:26 +00001380 int scno = known_scno(tcp);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001381
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001382 if (!(tcp->flags & TCB_INSYSCALL)) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001383 if (tcp->status.PR_WHY != PR_SYSENTRY) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001384 if (
1385 scno == SYS_fork
1386#ifdef SYS_vfork
1387 || scno == SYS_vfork
1388#endif /* SYS_vfork */
John Hughes4e36a812001-04-18 15:11:51 +00001389#ifdef SYS_fork1
1390 || scno == SYS_fork1
1391#endif /* SYS_fork1 */
1392#ifdef SYS_forkall
1393 || scno == SYS_forkall
1394#endif /* SYS_forkall */
1395#ifdef SYS_rfork1
1396 || scno == SYS_rfork1
1397#endif /* SYS_fork1 */
1398#ifdef SYS_rforkall
1399 || scno == SYS_rforkall
1400#endif /* SYS_rforkall */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001401 ) {
1402 /* We are returning in the child, fake it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001403 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001404 trace_syscall(tcp);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001405 tcp->status.PR_WHY = PR_SYSEXIT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001406 }
1407 else {
1408 fprintf(stderr, "syscall: missing entry\n");
1409 tcp->flags |= TCB_INSYSCALL;
1410 }
1411 }
1412 }
1413 else {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001414 if (tcp->status.PR_WHY != PR_SYSEXIT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001415 fprintf(stderr, "syscall: missing exit\n");
1416 tcp->flags &= ~TCB_INSYSCALL;
1417 }
1418 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001419#endif /* USE_PROCFS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001420#ifdef SUNOS4
1421 if (!(tcp->flags & TCB_INSYSCALL)) {
1422 if (scno == 0) {
1423 fprintf(stderr, "syscall: missing entry\n");
1424 tcp->flags |= TCB_INSYSCALL;
1425 }
1426 }
1427 else {
1428 if (scno != 0) {
1429 if (debug) {
1430 /*
1431 * This happens when a signal handler
1432 * for a signal which interrupted a
1433 * a system call makes another system call.
1434 */
1435 fprintf(stderr, "syscall: missing exit\n");
1436 }
1437 tcp->flags &= ~TCB_INSYSCALL;
1438 }
1439 }
1440#endif /* SUNOS4 */
1441#ifdef LINUX
1442#if defined (I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001443 if (upeek(tcp, 4*EAX, &eax) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001444 return -1;
1445 if (eax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1446 if (debug)
1447 fprintf(stderr, "stray syscall exit: eax = %ld\n", eax);
1448 return 0;
1449 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001450#elif defined (X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001451 if (upeek(tcp, 8*RAX, &rax) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00001452 return -1;
Roland McGrath998fac72004-06-23 01:40:45 +00001453 if (current_personality == 1)
1454 rax = (long int)(int)rax; /* sign extend from 32 bits */
Michal Ludvig0e035502002-09-23 15:41:01 +00001455 if (rax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1456 if (debug)
1457 fprintf(stderr, "stray syscall exit: rax = %ld\n", rax);
1458 return 0;
1459 }
Michal Ludvig10a88d02002-10-07 14:31:00 +00001460#elif defined (S390) || defined (S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001461 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001462 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001463 if (syscall_mode != -ENOSYS)
1464 syscall_mode = tcp->scno;
1465 if (gpr2 != syscall_mode && !(tcp->flags & TCB_INSYSCALL)) {
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001466 if (debug)
1467 fprintf(stderr, "stray syscall exit: gpr2 = %ld\n", gpr2);
1468 return 0;
1469 }
Roland McGrath96dc5142003-01-20 10:23:04 +00001470 else if (((tcp->flags & (TCB_INSYSCALL|TCB_WAITEXECVE))
1471 == (TCB_INSYSCALL|TCB_WAITEXECVE))
1472 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1473 /*
1474 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1475 * flag set for the post-execve SIGTRAP to see and reset.
1476 */
1477 gpr2 = 0;
1478 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001479#elif defined (POWERPC)
1480# define SO_MASK 0x10000000
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001481 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001482 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001483 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &result) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001484 return -1;
1485 if (flags & SO_MASK)
1486 result = -result;
1487#elif defined (M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001488 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001489 return -1;
1490 if (d0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1491 if (debug)
1492 fprintf(stderr, "stray syscall exit: d0 = %ld\n", d0);
1493 return 0;
1494 }
1495#elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001496 /*
1497 * Nothing required
1498 */
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001499#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001500 if (upeek(tcp, PT_R0, &r0) < 0)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001501 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001502#elif defined (HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001503 if (upeek(tcp, PT_GR28, &r28) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001504 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001505#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001506 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001507 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001508 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001509 return -1;
1510 if (ia32 && r8 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1511 if (debug)
1512 fprintf(stderr, "stray syscall exit: r8 = %ld\n", r8);
1513 return 0;
1514 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001515#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001516 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001517 return -1;
1518 if (r10 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1519 if (debug)
1520 fprintf(stderr, "stray syscall exit: r10 = %ld\n", r10);
1521 return 0;
1522 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001523#elif defined(MICROBLAZE)
1524 if (upeek(tcp, 3 * 4, &r3) < 0)
1525 return -1;
1526 if (r3 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1527 if (debug)
1528 fprintf(stderr, "stray syscall exit: r3 = %ld\n", r3);
1529 return 0;
1530 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001531#endif
1532#endif /* LINUX */
Pavel Machek4dc3b142000-02-01 17:58:41 +00001533 return 1;
1534}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001535
Roland McGrathc1e45922008-05-27 23:18:29 +00001536#ifdef LINUX
1537/*
1538 * Check the syscall return value register value for whether it is
1539 * a negated errno code indicating an error, or a success return value.
1540 */
1541static inline int
1542is_negated_errno(unsigned long int val)
1543{
1544 unsigned long int max = -(long int) nerrnos;
1545 if (personality_wordsize[current_personality] < sizeof(val)) {
1546 val = (unsigned int) val;
1547 max = (unsigned int) max;
1548 }
1549 return val > max;
1550}
1551#endif
1552
Roland McGratha4d48532005-06-08 20:45:28 +00001553static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001554get_error(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001555{
1556 int u_error = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001557#ifdef LINUX
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001558 int check_errno = 1;
1559 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
1560 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1561 check_errno = 0;
1562 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001563# if defined(S390) || defined(S390X)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001564 if (check_errno && is_negated_errno(gpr2)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001565 tcp->u_rval = -1;
1566 u_error = -gpr2;
1567 }
1568 else {
1569 tcp->u_rval = gpr2;
1570 u_error = 0;
1571 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001572# elif defined(I386)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001573 if (check_errno && is_negated_errno(eax)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001574 tcp->u_rval = -1;
1575 u_error = -eax;
1576 }
1577 else {
1578 tcp->u_rval = eax;
1579 u_error = 0;
1580 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001581# elif defined(X86_64)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001582 if (check_errno && is_negated_errno(rax)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001583 tcp->u_rval = -1;
1584 u_error = -rax;
1585 }
1586 else {
1587 tcp->u_rval = rax;
1588 u_error = 0;
1589 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001590# elif defined(IA64)
Roland McGrathc1e45922008-05-27 23:18:29 +00001591 if (ia32) {
1592 int err;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001593
Roland McGrathc1e45922008-05-27 23:18:29 +00001594 err = (int)r8;
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001595 if (check_errno && is_negated_errno(err)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001596 tcp->u_rval = -1;
1597 u_error = -err;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001598 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001599 else {
1600 tcp->u_rval = err;
1601 u_error = 0;
1602 }
1603 } else {
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001604 if (check_errno && r10) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001605 tcp->u_rval = -1;
1606 u_error = r8;
1607 } else {
1608 tcp->u_rval = r8;
1609 u_error = 0;
1610 }
1611 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001612# elif defined(MIPS)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001613 if (check_errno && a3) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001614 tcp->u_rval = -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001615 u_error = r2;
1616 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001617 tcp->u_rval = r2;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001618 u_error = 0;
1619 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001620# elif defined(POWERPC)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001621 if (check_errno && is_negated_errno(result)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001622 tcp->u_rval = -1;
1623 u_error = -result;
1624 }
1625 else {
1626 tcp->u_rval = result;
1627 u_error = 0;
1628 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001629# elif defined(M68K)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001630 if (check_errno && is_negated_errno(d0)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001631 tcp->u_rval = -1;
1632 u_error = -d0;
1633 }
1634 else {
1635 tcp->u_rval = d0;
1636 u_error = 0;
1637 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001638# elif defined(ARM)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001639 if (check_errno && is_negated_errno(regs.ARM_r0)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001640 tcp->u_rval = -1;
Roland McGrath0f87c492003-06-03 23:29:04 +00001641 u_error = -regs.ARM_r0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001642 }
1643 else {
Roland McGrath0f87c492003-06-03 23:29:04 +00001644 tcp->u_rval = regs.ARM_r0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001645 u_error = 0;
1646 }
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001647# elif defined(AVR32)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001648 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001649 tcp->u_rval = -1;
1650 u_error = -regs.r12;
1651 }
1652 else {
1653 tcp->u_rval = regs.r12;
1654 u_error = 0;
1655 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001656# elif defined(BFIN)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001657 if (check_errno && is_negated_errno(r0)) {
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001658 tcp->u_rval = -1;
1659 u_error = -r0;
1660 } else {
1661 tcp->u_rval = r0;
1662 u_error = 0;
1663 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001664# elif defined(ALPHA)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001665 if (check_errno && a3) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001666 tcp->u_rval = -1;
1667 u_error = r0;
1668 }
1669 else {
1670 tcp->u_rval = r0;
1671 u_error = 0;
1672 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001673# elif defined(SPARC)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001674 if (check_errno && regs.psr & PSR_C) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001675 tcp->u_rval = -1;
Mike Frysinger8566c502009-10-12 11:05:14 -04001676 u_error = regs.u_regs[U_REG_O0];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001677 }
1678 else {
Mike Frysinger8566c502009-10-12 11:05:14 -04001679 tcp->u_rval = regs.u_regs[U_REG_O0];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001680 u_error = 0;
1681 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001682# elif defined(SPARC64)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001683 if (check_errno && regs.tstate & 0x1100000000UL) {
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001684 tcp->u_rval = -1;
Mike Frysinger8566c502009-10-12 11:05:14 -04001685 u_error = regs.u_regs[U_REG_O0];
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001686 }
1687 else {
Mike Frysinger8566c502009-10-12 11:05:14 -04001688 tcp->u_rval = regs.u_regs[U_REG_O0];
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001689 u_error = 0;
1690 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001691# elif defined(HPPA)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001692 if (check_errno && is_negated_errno(r28)) {
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001693 tcp->u_rval = -1;
1694 u_error = -r28;
1695 }
1696 else {
1697 tcp->u_rval = r28;
1698 u_error = 0;
1699 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001700# elif defined(SH)
Roland McGrathc1e45922008-05-27 23:18:29 +00001701 /* interpret R0 as return value or error number */
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001702 if (check_errno && is_negated_errno(r0)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001703 tcp->u_rval = -1;
1704 u_error = -r0;
1705 }
1706 else {
1707 tcp->u_rval = r0;
1708 u_error = 0;
1709 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001710# elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001711 /* interpret result as return value or error number */
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001712 if (check_errno && is_negated_errno(r9)) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001713 tcp->u_rval = -1;
1714 u_error = -r9;
1715 }
1716 else {
1717 tcp->u_rval = r9;
1718 u_error = 0;
1719 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001720# elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001721 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001722 tcp->u_rval = -1;
1723 u_error = -r10;
1724 }
1725 else {
1726 tcp->u_rval = r10;
1727 u_error = 0;
1728 }
Chris Metcalfc8c66982009-12-28 10:00:15 -05001729# elif defined(TILE)
1730 long rval;
1731 /* interpret result as return value or error number */
1732 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1733 return -1;
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001734 if (check_errno && rval < 0 && rval > -nerrnos) {
Chris Metcalfc8c66982009-12-28 10:00:15 -05001735 tcp->u_rval = -1;
1736 u_error = -rval;
1737 }
1738 else {
1739 tcp->u_rval = rval;
1740 u_error = 0;
1741 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001742# elif defined(MICROBLAZE)
1743 /* interpret result as return value or error number */
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001744 if (check_errno && is_negated_errno(r3)) {
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001745 tcp->u_rval = -1;
1746 u_error = -r3;
1747 }
1748 else {
1749 tcp->u_rval = r3;
1750 u_error = 0;
1751 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001752# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001753#endif /* LINUX */
1754#ifdef SUNOS4
1755 /* get error code from user struct */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001756 if (upeek(tcp, uoff(u_error), &u_error) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001757 return -1;
1758 u_error >>= 24; /* u_error is a char */
1759
1760 /* get system call return value */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001761 if (upeek(tcp, uoff(u_rval1), &tcp->u_rval) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001762 return -1;
1763#endif /* SUNOS4 */
1764#ifdef SVR4
1765#ifdef SPARC
1766 /* Judicious guessing goes a long way. */
1767 if (tcp->status.pr_reg[R_PSR] & 0x100000) {
1768 tcp->u_rval = -1;
1769 u_error = tcp->status.pr_reg[R_O0];
1770 }
1771 else {
1772 tcp->u_rval = tcp->status.pr_reg[R_O0];
1773 u_error = 0;
1774 }
1775#endif /* SPARC */
1776#ifdef I386
1777 /* Wanna know how to kill an hour single-stepping? */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001778 if (tcp->status.PR_REG[EFL] & 0x1) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001779 tcp->u_rval = -1;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001780 u_error = tcp->status.PR_REG[EAX];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001781 }
1782 else {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001783 tcp->u_rval = tcp->status.PR_REG[EAX];
Wichert Akkerman16a03d22000-08-10 02:14:04 +00001784#ifdef HAVE_LONG_LONG
1785 tcp->u_lrval =
1786 ((unsigned long long) tcp->status.PR_REG[EDX] << 32) +
1787 tcp->status.PR_REG[EAX];
1788#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001789 u_error = 0;
1790 }
1791#endif /* I386 */
Michal Ludvig0e035502002-09-23 15:41:01 +00001792#ifdef X86_64
1793 /* Wanna know how to kill an hour single-stepping? */
1794 if (tcp->status.PR_REG[EFLAGS] & 0x1) {
1795 tcp->u_rval = -1;
1796 u_error = tcp->status.PR_REG[RAX];
1797 }
1798 else {
1799 tcp->u_rval = tcp->status.PR_REG[RAX];
1800 u_error = 0;
1801 }
1802#endif /* X86_64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001803#ifdef MIPS
1804 if (tcp->status.pr_reg[CTX_A3]) {
1805 tcp->u_rval = -1;
1806 u_error = tcp->status.pr_reg[CTX_V0];
1807 }
1808 else {
1809 tcp->u_rval = tcp->status.pr_reg[CTX_V0];
1810 u_error = 0;
1811 }
1812#endif /* MIPS */
1813#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001814#ifdef FREEBSD
1815 if (regs.r_eflags & PSL_C) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001816 tcp->u_rval = -1;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001817 u_error = regs.r_eax;
1818 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001819 tcp->u_rval = regs.r_eax;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001820 tcp->u_lrval =
1821 ((unsigned long long) regs.r_edx << 32) + regs.r_eax;
1822 u_error = 0;
1823 }
Roland McGrath761b5d72002-12-15 23:58:31 +00001824#endif /* FREEBSD */
Pavel Machek4dc3b142000-02-01 17:58:41 +00001825 tcp->u_error = u_error;
1826 return 1;
1827}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001828
Roland McGrathb69f81b2002-12-21 23:25:18 +00001829int
1830force_result(tcp, error, rval)
1831 struct tcb *tcp;
1832 int error;
1833 long rval;
1834{
1835#ifdef LINUX
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001836# if defined(S390) || defined(S390X)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001837 gpr2 = error ? -error : rval;
Roland McGrathb69f81b2002-12-21 23:25:18 +00001838 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_GPR2, gpr2) < 0)
1839 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001840# elif defined(I386)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001841 eax = error ? -error : rval;
1842 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(EAX * 4), eax) < 0)
1843 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001844# elif defined(X86_64)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001845 rax = error ? -error : rval;
Roland McGrath998fac72004-06-23 01:40:45 +00001846 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(RAX * 8), rax) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001847 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001848# elif defined(IA64)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001849 if (ia32) {
1850 r8 = error ? -error : rval;
1851 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0)
1852 return -1;
1853 }
1854 else {
1855 if (error) {
1856 r8 = error;
1857 r10 = -1;
1858 }
1859 else {
1860 r8 = rval;
1861 r10 = 0;
1862 }
1863 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0 ||
1864 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R10), r10) < 0)
1865 return -1;
1866 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001867# elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001868 r0 = error ? -error : rval;
1869 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_R0, r0) < 0)
1870 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001871# elif defined(MIPS)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001872 if (error) {
1873 r2 = error;
1874 a3 = -1;
1875 }
1876 else {
1877 r2 = rval;
1878 a3 = 0;
1879 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001880 /* PTRACE_POKEUSER is OK even for n32 since rval is only a long. */
Roland McGrathb69f81b2002-12-21 23:25:18 +00001881 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1882 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), r2) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001883 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001884# elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001885 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001886 return -1;
1887 if (error) {
1888 flags |= SO_MASK;
1889 result = error;
1890 }
1891 else {
1892 flags &= ~SO_MASK;
1893 result = rval;
1894 }
Roland McGratheb285352003-01-14 09:59:00 +00001895 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_CCR), flags) < 0 ||
1896 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_R3), result) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001897 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001898# elif defined(M68K)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001899 d0 = error ? -error : rval;
1900 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_D0), d0) < 0)
1901 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001902# elif defined(ARM)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001903 regs.ARM_r0 = error ? -error : rval;
1904 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*0), regs.ARM_r0) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001905 return -1;
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001906# elif defined(AVR32)
1907 regs.r12 = error ? -error : rval;
1908 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_R12, regs.r12) < 0)
1909 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001910# elif defined(ALPHA)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001911 if (error) {
1912 a3 = -1;
1913 r0 = error;
1914 }
1915 else {
1916 a3 = 0;
1917 r0 = rval;
1918 }
1919 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1920 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R0), r0) < 0)
1921 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001922# elif defined(SPARC)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001923 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1924 return -1;
1925 if (error) {
Mike Frysinger8566c502009-10-12 11:05:14 -04001926 regs.psr |= PSR_C;
1927 regs.u_regs[U_REG_O0] = error;
Roland McGrathb69f81b2002-12-21 23:25:18 +00001928 }
1929 else {
Mike Frysinger8566c502009-10-12 11:05:14 -04001930 regs.psr &= ~PSR_C;
1931 regs.u_regs[U_REG_O0] = rval;
Roland McGrathb69f81b2002-12-21 23:25:18 +00001932 }
1933 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1934 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001935# elif defined(SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001936 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1937 return -1;
1938 if (error) {
Mike Frysinger8566c502009-10-12 11:05:14 -04001939 regs.tstate |= 0x1100000000UL;
1940 regs.u_regs[U_REG_O0] = error;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001941 }
1942 else {
Mike Frysinger8566c502009-10-12 11:05:14 -04001943 regs.tstate &= ~0x1100000000UL;
1944 regs.u_regs[U_REG_O0] = rval;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001945 }
1946 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1947 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001948# elif defined(HPPA)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001949 r28 = error ? -error : rval;
1950 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR28), r28) < 0)
1951 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001952# elif defined(SH)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001953 r0 = error ? -error : rval;
1954 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*REG_REG0), r0) < 0)
1955 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001956# elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001957 r9 = error ? -error : rval;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001958 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_GENERAL(9), r9) < 0)
1959 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001960# endif
Roland McGrathb69f81b2002-12-21 23:25:18 +00001961#endif /* LINUX */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001962
Roland McGrathb69f81b2002-12-21 23:25:18 +00001963#ifdef SUNOS4
Roland McGratheb9e2e82009-06-02 16:49:22 -07001964 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_error),
1965 error << 24) < 0 ||
1966 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_rval1), rval) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001967 return -1;
1968#endif /* SUNOS4 */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001969
Roland McGrathb69f81b2002-12-21 23:25:18 +00001970#ifdef SVR4
1971 /* XXX no clue */
1972 return -1;
1973#endif /* SVR4 */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001974
Roland McGrathb69f81b2002-12-21 23:25:18 +00001975#ifdef FREEBSD
1976 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001977 perror("pread");
1978 return -1;
1979 }
Roland McGrathb69f81b2002-12-21 23:25:18 +00001980 if (error) {
1981 regs.r_eflags |= PSL_C;
1982 regs.r_eax = error;
1983 }
1984 else {
1985 regs.r_eflags &= ~PSL_C;
1986 regs.r_eax = rval;
1987 }
1988 if (pwrite(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001989 perror("pwrite");
1990 return -1;
1991 }
Roland McGrathb69f81b2002-12-21 23:25:18 +00001992#endif /* FREEBSD */
1993
1994 /* All branches reach here on success (only). */
1995 tcp->u_error = error;
1996 tcp->u_rval = rval;
1997 return 0;
1998}
1999
Roland McGratha4d48532005-06-08 20:45:28 +00002000static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002001syscall_enter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002002{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002003#ifdef LINUX
Michal Ludvig10a88d02002-10-07 14:31:00 +00002004#if defined(S390) || defined(S390X)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00002005 {
2006 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002007 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2008 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002009 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002010 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00002011 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002012 if (upeek(tcp,i==0 ? PT_ORIGGPR2:PT_GPR2+i*sizeof(long), &tcp->u_arg[i]) < 0)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00002013 return -1;
2014 }
2015 }
2016#elif defined (ALPHA)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002017 {
2018 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002019 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2020 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002021 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002022 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002023 for (i = 0; i < tcp->u_nargs; i++) {
Wichert Akkermanb859bea1999-04-18 22:50:50 +00002024 /* WTA: if scno is out-of-bounds this will bomb. Add range-check
2025 * for scno somewhere above here!
2026 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002027 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002028 return -1;
2029 }
2030 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002031#elif defined (IA64)
2032 {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002033 if (!ia32) {
Jan Kratochvil1f942712008-08-06 21:38:52 +00002034 unsigned long *out0, cfm, sof, sol, i;
2035 long rbs_end;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002036 /* be backwards compatible with kernel < 2.4.4... */
2037# ifndef PT_RBS_END
2038# define PT_RBS_END PT_AR_BSP
2039# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002040
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002041 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002042 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002043 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002044 return -1;
2045
2046 sof = (cfm >> 0) & 0x7f;
2047 sol = (cfm >> 7) & 0x7f;
Jan Kratochvil1f942712008-08-06 21:38:52 +00002048 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002049
2050 if (tcp->scno >= 0 && tcp->scno < nsyscalls
2051 && sysent[tcp->scno].nargs != -1)
2052 tcp->u_nargs = sysent[tcp->scno].nargs;
2053 else
2054 tcp->u_nargs = MAX_ARGS;
2055 for (i = 0; i < tcp->u_nargs; ++i) {
2056 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
2057 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
2058 return -1;
2059 }
2060 } else {
2061 int i;
2062
2063 if (/* EBX = out0 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002064 upeek(tcp, PT_R11, (long *) &tcp->u_arg[0]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002065 /* ECX = out1 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002066 || upeek(tcp, PT_R9, (long *) &tcp->u_arg[1]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002067 /* EDX = out2 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002068 || upeek(tcp, PT_R10, (long *) &tcp->u_arg[2]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002069 /* ESI = out3 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002070 || upeek(tcp, PT_R14, (long *) &tcp->u_arg[3]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002071 /* EDI = out4 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002072 || upeek(tcp, PT_R15, (long *) &tcp->u_arg[4]) < 0
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002073 /* EBP = out5 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002074 || upeek(tcp, PT_R13, (long *) &tcp->u_arg[5]) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002075 return -1;
2076
2077 for (i = 0; i < 6; ++i)
2078 /* truncate away IVE sign-extension */
2079 tcp->u_arg[i] &= 0xffffffff;
2080
2081 if (tcp->scno >= 0 && tcp->scno < nsyscalls
2082 && sysent[tcp->scno].nargs != -1)
2083 tcp->u_nargs = sysent[tcp->scno].nargs;
2084 else
2085 tcp->u_nargs = 5;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002086 }
2087 }
Roland McGrath542c2c62008-05-20 01:11:56 +00002088#elif defined (LINUX_MIPSN32) || defined (LINUX_MIPSN64)
2089 /* N32 and N64 both use up to six registers. */
2090 {
2091 unsigned long long regs[38];
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002092 int i, nargs;
Roland McGrath542c2c62008-05-20 01:11:56 +00002093
2094 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2095 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrathc1e45922008-05-27 23:18:29 +00002096 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002097 nargs = tcp->u_nargs = MAX_ARGS;
Roland McGrath542c2c62008-05-20 01:11:56 +00002098
David Daney20037042010-02-09 21:22:30 +00002099 if (ptrace (PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00002100 return -1;
2101
Roland McGratheb9e2e82009-06-02 16:49:22 -07002102 for(i = 0; i < nargs; i++) {
Roland McGrath542c2c62008-05-20 01:11:56 +00002103 tcp->u_arg[i] = regs[REG_A0 + i];
2104# if defined (LINUX_MIPSN32)
2105 tcp->ext_arg[i] = regs[REG_A0 + i];
2106# endif
2107 }
2108 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00002109#elif defined (MIPS)
2110 {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002111 long sp;
2112 int i, nargs;
Wichert Akkermanf90da011999-10-31 21:15:38 +00002113
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002114 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2115 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002116 else
Dmitry V. Levin414fe7d2009-07-08 11:21:17 +00002117 nargs = tcp->u_nargs = MAX_ARGS;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002118 if(nargs > 4) {
Dmitry V. Levin414fe7d2009-07-08 11:21:17 +00002119 if(upeek(tcp, REG_SP, &sp) < 0)
2120 return -1;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002121 for(i = 0; i < 4; i++) {
Dmitry V. Levin414fe7d2009-07-08 11:21:17 +00002122 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i])<0)
2123 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00002124 }
2125 umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]),
2126 (char *)(tcp->u_arg + 4));
2127 } else {
Dmitry V. Levin414fe7d2009-07-08 11:21:17 +00002128 for(i = 0; i < nargs; i++) {
2129 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
2130 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00002131 }
2132 }
2133 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002134#elif defined (POWERPC)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002135# ifndef PT_ORIG_R3
2136# define PT_ORIG_R3 34
2137# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002138 {
2139 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002140 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2141 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002142 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002143 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002144 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002145 if (upeek(tcp, (i==0) ?
Roland McGratheb285352003-01-14 09:59:00 +00002146 (sizeof(unsigned long)*PT_ORIG_R3) :
2147 ((i+PT_R3)*sizeof(unsigned long)),
2148 &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002149 return -1;
2150 }
2151 }
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002152#elif defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002153 {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002154 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002155
2156 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2157 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002158 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002159 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002160 for (i = 0; i < tcp->u_nargs; i++)
Mike Frysinger8566c502009-10-12 11:05:14 -04002161 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002162 }
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002163#elif defined (HPPA)
2164 {
2165 int i;
2166
2167 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2168 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002169 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002170 tcp->u_nargs = MAX_ARGS;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002171 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002172 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002173 return -1;
2174 }
2175 }
Roland McGrath0f87c492003-06-03 23:29:04 +00002176#elif defined(ARM)
2177 {
2178 int i;
2179
2180 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2181 tcp->u_nargs = sysent[tcp->scno].nargs;
2182 else
2183 tcp->u_nargs = MAX_ARGS;
2184 for (i = 0; i < tcp->u_nargs; i++)
2185 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002186 }
2187#elif defined(AVR32)
2188 tcp->u_nargs = sysent[tcp->scno].nargs;
2189 tcp->u_arg[0] = regs.r12;
2190 tcp->u_arg[1] = regs.r11;
2191 tcp->u_arg[2] = regs.r10;
2192 tcp->u_arg[3] = regs.r9;
2193 tcp->u_arg[4] = regs.r5;
2194 tcp->u_arg[5] = regs.r3;
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00002195#elif defined(BFIN)
2196 {
2197 int i;
2198 int argreg[] = {PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5};
2199
2200 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2201 tcp->u_nargs = sysent[tcp->scno].nargs;
2202 else
2203 tcp->u_nargs = sizeof(argreg) / sizeof(argreg[0]);
2204
2205 for (i = 0; i < tcp->u_nargs; ++i)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002206 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00002207 return -1;
2208 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00002209#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002210 {
2211 int i;
2212 static int syscall_regs[] = {
2213 REG_REG0+4, REG_REG0+5, REG_REG0+6, REG_REG0+7,
2214 REG_REG0, REG_REG0+1, REG_REG0+2
2215 };
Wichert Akkermanccef6372002-05-01 16:39:22 +00002216
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002217 tcp->u_nargs = sysent[tcp->scno].nargs;
2218 for (i = 0; i < tcp->u_nargs; i++) {
2219 if (upeek(tcp, 4*syscall_regs[i], &tcp->u_arg[i]) < 0)
2220 return -1;
2221 }
2222 }
Roland McGrathf5a47772003-06-26 22:40:42 +00002223#elif defined(SH64)
Roland McGrathe1e584b2003-06-02 19:18:58 +00002224 {
2225 int i;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002226 /* Registers used by SH5 Linux system calls for parameters */
Roland McGrathe1e584b2003-06-02 19:18:58 +00002227 static int syscall_regs[] = { 2, 3, 4, 5, 6, 7 };
2228
2229 /*
2230 * TODO: should also check that the number of arguments encoded
2231 * in the trap number matches the number strace expects.
2232 */
2233 /*
Dmitry V. Levin414fe7d2009-07-08 11:21:17 +00002234 assert(sysent[tcp->scno].nargs <
2235 sizeof(syscall_regs)/sizeof(syscall_regs[0]));
Roland McGrathe1e584b2003-06-02 19:18:58 +00002236 */
2237
2238 tcp->u_nargs = sysent[tcp->scno].nargs;
2239 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002240 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00002241 return -1;
2242 }
2243 }
2244
Michal Ludvig0e035502002-09-23 15:41:01 +00002245#elif defined(X86_64)
2246 {
2247 int i;
2248 static int argreg[SUPPORTED_PERSONALITIES][MAX_ARGS] = {
2249 {RDI,RSI,RDX,R10,R8,R9}, /* x86-64 ABI */
Roland McGrath5a9c6ad2005-02-02 03:06:52 +00002250 {RBX,RCX,RDX,RSI,RDI,RBP} /* i386 ABI */
Michal Ludvig0e035502002-09-23 15:41:01 +00002251 };
Roland McGrath761b5d72002-12-15 23:58:31 +00002252
Michal Ludvig0e035502002-09-23 15:41:01 +00002253 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2254 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002255 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002256 tcp->u_nargs = MAX_ARGS;
Michal Ludvig0e035502002-09-23 15:41:01 +00002257 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002258 if (upeek(tcp, argreg[current_personality][i]*8, &tcp->u_arg[i]) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00002259 return -1;
2260 }
2261 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02002262#elif defined(MICROBLAZE)
2263 {
2264 int i;
2265 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
2266 tcp->u_nargs = sysent[tcp->scno].nargs;
2267 else
2268 tcp->u_nargs = 0;
2269 for (i = 0; i < tcp->u_nargs; i++) {
2270 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
2271 return -1;
2272 }
2273 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002274#elif defined(CRISV10) || defined(CRISV32)
2275 {
2276 int i;
2277 static const int crisregs[] = {
2278 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
2279 4*PT_R13, 4*PT_MOF, 4*PT_SRP
2280 };
2281
2282 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
2283 tcp->u_nargs = sysent[tcp->scno].nargs;
2284 else
2285 tcp->u_nargs = 0;
2286 for (i = 0; i < tcp->u_nargs; i++) {
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00002287 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002288 return -1;
2289 }
2290 }
Chris Metcalfc8c66982009-12-28 10:00:15 -05002291#elif defined(TILE)
2292 {
2293 int i;
2294 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2295 tcp->u_nargs = sysent[tcp->scno].nargs;
2296 else
2297 tcp->u_nargs = MAX_ARGS;
2298 for (i = 0; i < tcp->u_nargs; ++i) {
2299 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
2300 return -1;
2301 }
2302 }
Andreas Schwab246888d2010-06-05 21:50:30 +02002303#elif defined (M68K)
2304 {
2305 int i;
2306 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2307 tcp->u_nargs = sysent[tcp->scno].nargs;
2308 else
2309 tcp->u_nargs = MAX_ARGS;
2310 for (i = 0; i < tcp->u_nargs; i++) {
2311 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
2312 return -1;
2313 }
2314 }
Wichert Akkermanfaf72222000-02-19 23:59:03 +00002315#else /* Other architecture (like i386) (32bits specific) */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002316 {
2317 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002318 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2319 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002320 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002321 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002322 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002323 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002324 return -1;
2325 }
2326 }
Roland McGrath761b5d72002-12-15 23:58:31 +00002327#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002328#endif /* LINUX */
2329#ifdef SUNOS4
2330 {
2331 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002332 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2333 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002334 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002335 tcp->u_nargs = MAX_ARGS;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002336 for (i = 0; i < tcp->u_nargs; i++) {
2337 struct user *u;
2338
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002339 if (upeek(tcp, uoff(u_arg[0]) +
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002340 (i*sizeof(u->u_arg[0])), &tcp->u_arg[i]) < 0)
2341 return -1;
2342 }
2343 }
2344#endif /* SUNOS4 */
2345#ifdef SVR4
2346#ifdef MIPS
2347 /*
2348 * SGI is broken: even though it has pr_sysarg, it doesn't
2349 * set them on system call entry. Get a clue.
2350 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002351 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002352 tcp->u_nargs = sysent[tcp->scno].nargs;
2353 else
2354 tcp->u_nargs = tcp->status.pr_nsysarg;
2355 if (tcp->u_nargs > 4) {
2356 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2357 4*sizeof(tcp->u_arg[0]));
2358 umoven(tcp, tcp->status.pr_reg[CTX_SP] + 16,
2359 (tcp->u_nargs - 4)*sizeof(tcp->u_arg[0]), (char *) (tcp->u_arg + 4));
2360 }
2361 else {
2362 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2363 tcp->u_nargs*sizeof(tcp->u_arg[0]));
2364 }
John Hughes25299712001-03-06 10:10:06 +00002365#elif UNIXWARE >= 2
2366 /*
2367 * Like SGI, UnixWare doesn't set pr_sysarg until system call exit
2368 */
2369 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2370 tcp->u_nargs = sysent[tcp->scno].nargs;
2371 else
2372 tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;
2373 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
2374 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2375#elif defined (HAVE_PR_SYSCALL)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002376 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002377 tcp->u_nargs = sysent[tcp->scno].nargs;
2378 else
2379 tcp->u_nargs = tcp->status.pr_nsysarg;
2380 {
2381 int i;
2382 for (i = 0; i < tcp->u_nargs; i++)
2383 tcp->u_arg[i] = tcp->status.pr_sysarg[i];
2384 }
John Hughes25299712001-03-06 10:10:06 +00002385#elif defined (I386)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002386 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002387 tcp->u_nargs = sysent[tcp->scno].nargs;
2388 else
2389 tcp->u_nargs = 5;
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002390 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002391 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
John Hughes25299712001-03-06 10:10:06 +00002392#else
2393 I DONT KNOW WHAT TO DO
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002394#endif /* !HAVE_PR_SYSCALL */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002395#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002396#ifdef FREEBSD
2397 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2398 sysent[tcp->scno].nargs > tcp->status.val)
2399 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002400 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002401 tcp->u_nargs = tcp->status.val;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002402 if (tcp->u_nargs < 0)
2403 tcp->u_nargs = 0;
2404 if (tcp->u_nargs > MAX_ARGS)
2405 tcp->u_nargs = MAX_ARGS;
2406 switch(regs.r_eax) {
2407 case SYS___syscall:
2408 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2409 regs.r_esp + sizeof(int) + sizeof(quad_t));
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002410 break;
2411 case SYS_syscall:
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002412 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2413 regs.r_esp + 2 * sizeof(int));
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002414 break;
2415 default:
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002416 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2417 regs.r_esp + sizeof(int));
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002418 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002419 }
2420#endif /* FREEBSD */
Pavel Machek4dc3b142000-02-01 17:58:41 +00002421 return 1;
2422}
2423
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002424static int
2425trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002426{
2427 int sys_res;
2428 struct timeval tv;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002429 int res, scno_good;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002430 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002431
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002432 /* Measure the exit time as early as possible to avoid errors. */
2433 if (dtime || cflag)
2434 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002435
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002436 /* BTW, why we don't just memorize syscall no. on entry
2437 * in tcp->something?
2438 */
2439 scno_good = res = get_scno(tcp);
2440 if (res == 0)
2441 return res;
2442 if (res == 1)
2443 res = syscall_fixup(tcp);
2444 if (res == 0)
2445 return res;
2446 if (res == 1)
2447 res = get_error(tcp);
2448 if (res == 0)
2449 return res;
2450 if (res == 1)
2451 internal_syscall(tcp);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002452
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002453 if (res == 1 && tcp->scno >= 0 && tcp->scno < nsyscalls &&
2454 !(qual_flags[tcp->scno] & QUAL_TRACE)) {
Pavel Machek4dc3b142000-02-01 17:58:41 +00002455 tcp->flags &= ~TCB_INSYSCALL;
2456 return 0;
2457 }
2458
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002459 if (tcp->flags & TCB_REPRINT) {
2460 printleader(tcp);
2461 tprintf("<... ");
2462 if (scno_good != 1)
2463 tprintf("????");
2464 else if (tcp->scno >= nsyscalls || tcp->scno < 0)
2465 tprintf("syscall_%lu", tcp->scno);
2466 else
2467 tprintf("%s", sysent[tcp->scno].sys_name);
2468 tprintf(" resumed> ");
2469 }
2470
2471 if (cflag) {
2472 struct timeval t = tv;
2473 int rc = count_syscall(tcp, &t);
2474 if (cflag == CFLAG_ONLY_STATS)
2475 {
2476 tcp->flags &= ~TCB_INSYSCALL;
2477 return rc;
2478 }
2479 }
2480
2481 if (res != 1) {
2482 tprintf(") ");
2483 tabto(acolumn);
2484 tprintf("= ? <unavailable>");
2485 printtrailer();
2486 tcp->flags &= ~TCB_INSYSCALL;
2487 return res;
2488 }
2489
2490 if (tcp->scno >= nsyscalls || tcp->scno < 0
2491 || (qual_flags[tcp->scno] & QUAL_RAW))
2492 sys_res = printargs(tcp);
2493 else {
2494 if (not_failing_only && tcp->u_error)
2495 return 0; /* ignore failed syscalls */
2496 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2497 }
2498
2499 u_error = tcp->u_error;
2500 tprintf(") ");
2501 tabto(acolumn);
2502 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2503 qual_flags[tcp->scno] & QUAL_RAW) {
2504 if (u_error)
2505 tprintf("= -1 (errno %ld)", u_error);
2506 else
2507 tprintf("= %#lx", tcp->u_rval);
2508 }
2509 else if (!(sys_res & RVAL_NONE) && u_error) {
2510 switch (u_error) {
2511#ifdef LINUX
2512 case ERESTARTSYS:
2513 tprintf("= ? ERESTARTSYS (To be restarted)");
2514 break;
2515 case ERESTARTNOINTR:
2516 tprintf("= ? ERESTARTNOINTR (To be restarted)");
2517 break;
2518 case ERESTARTNOHAND:
2519 tprintf("= ? ERESTARTNOHAND (To be restarted)");
2520 break;
2521 case ERESTART_RESTARTBLOCK:
2522 tprintf("= ? ERESTART_RESTARTBLOCK (To be restarted)");
2523 break;
2524#endif /* LINUX */
2525 default:
2526 tprintf("= -1 ");
2527 if (u_error < 0)
2528 tprintf("E??? (errno %ld)", u_error);
2529 else if (u_error < nerrnos)
2530 tprintf("%s (%s)", errnoent[u_error],
2531 strerror(u_error));
2532 else
2533 tprintf("ERRNO_%ld (%s)", u_error,
2534 strerror(u_error));
2535 break;
2536 }
2537 if ((sys_res & RVAL_STR) && tcp->auxstr)
2538 tprintf(" (%s)", tcp->auxstr);
2539 }
2540 else {
2541 if (sys_res & RVAL_NONE)
2542 tprintf("= ?");
2543 else {
2544 switch (sys_res & RVAL_MASK) {
2545 case RVAL_HEX:
2546 tprintf("= %#lx", tcp->u_rval);
2547 break;
2548 case RVAL_OCTAL:
2549 tprintf("= %#lo", tcp->u_rval);
2550 break;
2551 case RVAL_UDECIMAL:
2552 tprintf("= %lu", tcp->u_rval);
2553 break;
2554 case RVAL_DECIMAL:
2555 tprintf("= %ld", tcp->u_rval);
2556 break;
2557#ifdef HAVE_LONG_LONG
2558 case RVAL_LHEX:
2559 tprintf("= %#llx", tcp->u_lrval);
2560 break;
2561 case RVAL_LOCTAL:
2562 tprintf("= %#llo", tcp->u_lrval);
2563 break;
2564 case RVAL_LUDECIMAL:
2565 tprintf("= %llu", tcp->u_lrval);
2566 break;
2567 case RVAL_LDECIMAL:
2568 tprintf("= %lld", tcp->u_lrval);
2569 break;
2570#endif
2571 default:
2572 fprintf(stderr,
2573 "invalid rval format\n");
2574 break;
2575 }
2576 }
2577 if ((sys_res & RVAL_STR) && tcp->auxstr)
2578 tprintf(" (%s)", tcp->auxstr);
2579 }
2580 if (dtime) {
2581 tv_sub(&tv, &tv, &tcp->etime);
2582 tprintf(" <%ld.%06ld>",
2583 (long) tv.tv_sec, (long) tv.tv_usec);
2584 }
2585 printtrailer();
2586
2587 dumpio(tcp);
2588 if (fflush(tcp->outf) == EOF)
2589 return -1;
2590 tcp->flags &= ~TCB_INSYSCALL;
2591 return 0;
2592}
2593
2594static int
2595trace_syscall_entering(struct tcb *tcp)
2596{
2597 int sys_res;
2598 int res, scno_good;
2599
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002600 scno_good = res = get_scno(tcp);
2601 if (res == 0)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002602 return res;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002603 if (res == 1)
2604 res = syscall_fixup(tcp);
2605 if (res == 0)
2606 return res;
2607 if (res == 1)
2608 res = syscall_enter(tcp);
2609 if (res == 0)
2610 return res;
2611
2612 if (res != 1) {
2613 printleader(tcp);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002614 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002615 tcp_last = tcp;
2616 if (scno_good != 1)
Roland McGratheb9e2e82009-06-02 16:49:22 -07002617 tprintf("????" /* anti-trigraph gap */ "(");
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002618 else if (tcp->scno >= nsyscalls || tcp->scno < 0)
2619 tprintf("syscall_%lu(", tcp->scno);
2620 else
2621 tprintf("%s(", sysent[tcp->scno].sys_name);
Roland McGratheb9e2e82009-06-02 16:49:22 -07002622 /*
2623 * " <unavailable>" will be added later by the code which
2624 * detects ptrace errors.
2625 */
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002626 tcp->flags |= TCB_INSYSCALL;
2627 return res;
2628 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002629
Roland McGrath17352792005-06-07 23:21:26 +00002630 switch (known_scno(tcp)) {
Roland McGrathd5bd7e62008-08-25 03:16:26 +00002631#ifdef SYS_socket_subcall
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002632 case SYS_socketcall:
2633 decode_subcall(tcp, SYS_socket_subcall,
2634 SYS_socket_nsubcalls, deref_style);
2635 break;
Roland McGrathd5bd7e62008-08-25 03:16:26 +00002636#endif
2637#ifdef SYS_ipc_subcall
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002638 case SYS_ipc:
2639 decode_subcall(tcp, SYS_ipc_subcall,
2640 SYS_ipc_nsubcalls, shift_style);
2641 break;
Roland McGrathd5bd7e62008-08-25 03:16:26 +00002642#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002643#ifdef SVR4
2644#ifdef SYS_pgrpsys_subcall
2645 case SYS_pgrpsys:
2646 decode_subcall(tcp, SYS_pgrpsys_subcall,
2647 SYS_pgrpsys_nsubcalls, shift_style);
2648 break;
2649#endif /* SYS_pgrpsys_subcall */
2650#ifdef SYS_sigcall_subcall
2651 case SYS_sigcall:
2652 decode_subcall(tcp, SYS_sigcall_subcall,
2653 SYS_sigcall_nsubcalls, mask_style);
2654 break;
2655#endif /* SYS_sigcall_subcall */
2656 case SYS_msgsys:
2657 decode_subcall(tcp, SYS_msgsys_subcall,
2658 SYS_msgsys_nsubcalls, shift_style);
2659 break;
2660 case SYS_shmsys:
2661 decode_subcall(tcp, SYS_shmsys_subcall,
2662 SYS_shmsys_nsubcalls, shift_style);
2663 break;
2664 case SYS_semsys:
2665 decode_subcall(tcp, SYS_semsys_subcall,
2666 SYS_semsys_nsubcalls, shift_style);
2667 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002668 case SYS_sysfs:
2669 decode_subcall(tcp, SYS_sysfs_subcall,
2670 SYS_sysfs_nsubcalls, shift_style);
2671 break;
2672 case SYS_spcall:
2673 decode_subcall(tcp, SYS_spcall_subcall,
2674 SYS_spcall_nsubcalls, shift_style);
2675 break;
2676#ifdef SYS_context_subcall
2677 case SYS_context:
2678 decode_subcall(tcp, SYS_context_subcall,
2679 SYS_context_nsubcalls, shift_style);
2680 break;
2681#endif /* SYS_context_subcall */
Wichert Akkerman8829a551999-06-11 13:18:40 +00002682#ifdef SYS_door_subcall
2683 case SYS_door:
2684 decode_subcall(tcp, SYS_door_subcall,
2685 SYS_door_nsubcalls, door_style);
2686 break;
2687#endif /* SYS_door_subcall */
John Hughesbdf48f52001-03-06 15:08:09 +00002688#ifdef SYS_kaio_subcall
2689 case SYS_kaio:
2690 decode_subcall(tcp, SYS_kaio_subcall,
2691 SYS_kaio_nsubcalls, shift_style);
2692 break;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002693#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002694#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002695#ifdef FREEBSD
2696 case SYS_msgsys:
2697 case SYS_shmsys:
2698 case SYS_semsys:
2699 decode_subcall(tcp, 0, 0, table_style);
2700 break;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00002701#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002702#ifdef SUNOS4
2703 case SYS_semsys:
2704 decode_subcall(tcp, SYS_semsys_subcall,
2705 SYS_semsys_nsubcalls, shift_style);
2706 break;
2707 case SYS_msgsys:
2708 decode_subcall(tcp, SYS_msgsys_subcall,
2709 SYS_msgsys_nsubcalls, shift_style);
2710 break;
2711 case SYS_shmsys:
2712 decode_subcall(tcp, SYS_shmsys_subcall,
2713 SYS_shmsys_nsubcalls, shift_style);
2714 break;
2715#endif
2716 }
2717
2718 internal_syscall(tcp);
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002719 if (tcp->scno >=0 && tcp->scno < nsyscalls && !(qual_flags[tcp->scno] & QUAL_TRACE)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002720 tcp->flags |= TCB_INSYSCALL;
2721 return 0;
2722 }
2723
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002724 if (cflag == CFLAG_ONLY_STATS) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002725 tcp->flags |= TCB_INSYSCALL;
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002726 gettimeofday(&tcp->etime, NULL);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002727 return 0;
2728 }
2729
2730 printleader(tcp);
2731 tcp->flags &= ~TCB_REPRINT;
2732 tcp_last = tcp;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002733 if (tcp->scno >= nsyscalls || tcp->scno < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002734 tprintf("syscall_%lu(", tcp->scno);
2735 else
2736 tprintf("%s(", sysent[tcp->scno].sys_name);
Roland McGrath761b5d72002-12-15 23:58:31 +00002737 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002738 ((qual_flags[tcp->scno] & QUAL_RAW) && tcp->scno != SYS_exit))
2739 sys_res = printargs(tcp);
2740 else
2741 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2742 if (fflush(tcp->outf) == EOF)
2743 return -1;
2744 tcp->flags |= TCB_INSYSCALL;
2745 /* Measure the entrance time as late as possible to avoid errors. */
Dmitry V. Levine3a7ef52010-03-28 19:24:54 +00002746 if (dtime || cflag)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002747 gettimeofday(&tcp->etime, NULL);
2748 return sys_res;
2749}
2750
2751int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002752trace_syscall(struct tcb *tcp)
2753{
2754 return exiting(tcp) ?
2755 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2756}
2757
2758int
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002759printargs(tcp)
2760struct tcb *tcp;
2761{
2762 if (entering(tcp)) {
2763 int i;
2764
2765 for (i = 0; i < tcp->u_nargs; i++)
2766 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
2767 }
2768 return 0;
2769}
2770
2771long
2772getrval2(tcp)
2773struct tcb *tcp;
2774{
2775 long val = -1;
2776
2777#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002778#if defined (SPARC) || defined (SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04002779 struct pt_regs regs;
Roland McGratheb9e2e82009-06-02 16:49:22 -07002780 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002781 return -1;
Mike Frysinger8566c502009-10-12 11:05:14 -04002782 val = regs.u_regs[U_REG_O1];
Roland McGrath6b1d43e2003-03-31 01:05:01 +00002783#elif defined(SH)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002784 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
Roland McGrath6b1d43e2003-03-31 01:05:01 +00002785 return -1;
Roland McGrathb4ce1762004-03-01 20:30:48 +00002786#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002787 if (upeek(tcp, PT_R9, &val) < 0)
Roland McGrathb4ce1762004-03-01 20:30:48 +00002788 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002789#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002790#endif /* LINUX */
2791
2792#ifdef SUNOS4
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002793 if (upeek(tcp, uoff(u_rval2), &val) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002794 return -1;
2795#endif /* SUNOS4 */
2796
2797#ifdef SVR4
2798#ifdef SPARC
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002799 val = tcp->status.PR_REG[R_O1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002800#endif /* SPARC */
2801#ifdef I386
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002802 val = tcp->status.PR_REG[EDX];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002803#endif /* I386 */
Michal Ludvig0e035502002-09-23 15:41:01 +00002804#ifdef X86_64
2805 val = tcp->status.PR_REG[RDX];
2806#endif /* X86_64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002807#ifdef MIPS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002808 val = tcp->status.PR_REG[CTX_V1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002809#endif /* MIPS */
2810#endif /* SVR4 */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002811
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002812#ifdef FREEBSD
2813 struct reg regs;
2814 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
2815 val = regs.r_edx;
Roland McGrath761b5d72002-12-15 23:58:31 +00002816#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002817 return val;
2818}
2819
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +00002820#ifdef SUNOS4
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002821/*
2822 * Apparently, indirect system calls have already be converted by ptrace(2),
2823 * so if you see "indir" this program has gone astray.
2824 */
2825int
2826sys_indir(tcp)
2827struct tcb *tcp;
2828{
2829 int i, scno, nargs;
2830
2831 if (entering(tcp)) {
2832 if ((scno = tcp->u_arg[0]) > nsyscalls) {
2833 fprintf(stderr, "Bogus syscall: %u\n", scno);
2834 return 0;
2835 }
2836 nargs = sysent[scno].nargs;
2837 tprintf("%s", sysent[scno].sys_name);
2838 for (i = 0; i < nargs; i++)
2839 tprintf(", %#lx", tcp->u_arg[i+1]);
2840 }
2841 return 0;
2842}
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +00002843#endif /* SUNOS4 */
Dmitry V. Levin2e55ff42008-09-03 01:02:46 +00002844
2845int
2846is_restart_error(struct tcb *tcp)
2847{
2848#ifdef LINUX
2849 if (!syserror(tcp))
2850 return 0;
2851 switch (tcp->u_error) {
2852 case ERESTARTSYS:
2853 case ERESTARTNOINTR:
2854 case ERESTARTNOHAND:
2855 case ERESTART_RESTARTBLOCK:
2856 return 1;
2857 default:
2858 break;
2859 }
2860#endif /* LINUX */
2861 return 0;
2862}