blob: 1801a7c41a2b0fad7508f3e15d8da59bf55159e2 [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
Denys Vlasenko041b3ee2011-08-18 12:48:56 +020093#warning: NSIG is not defined, using 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000094#define NSIG 32
95#endif
96#ifdef ARM
Denys Vlasenko041b3ee2011-08-18 12:48:56 +020097/* Ugh. Is this really correct? ARM has no RT signals?! */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000098#undef NSIG
99#define NSIG 32
Pavel Machekd8ae7e32000-02-01 17:17:25 +0000100#undef NR_SYSCALL_BASE
101#define NR_SYSCALL_BASE __NR_SYSCALL_BASE
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102#endif
103#endif /* LINUX */
104
105#include "syscall.h"
106
107/* Define these shorthand notations to simplify the syscallent files. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000108#define TD TRACE_DESC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000109#define TF TRACE_FILE
110#define TI TRACE_IPC
111#define TN TRACE_NETWORK
112#define TP TRACE_PROCESS
113#define TS TRACE_SIGNAL
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000114#define NF SYSCALL_NEVER_FAILS
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200115#define MA MAX_ARGS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000116
Roland McGrathee36ce12004-09-04 03:53:10 +0000117static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118#include "syscallent.h"
119};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120
121#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000122static const struct sysent sysent1[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000123#include "syscallent1.h"
124};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200125#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000126
127#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000128static const struct sysent sysent2[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000129#include "syscallent2.h"
130};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200131#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000132
133/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000134#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000135#undef TF
136#undef TI
137#undef TN
138#undef TP
139#undef TS
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000140#undef NF
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200141#undef MA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142
Denys Vlasenko39fca622011-08-20 02:12:33 +0200143
144/*
145 * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
146 * program `ioctlsort', such that the list is sorted by the `code' field.
147 * This has the side-effect of resolving the _IO.. macros into
148 * plain integers, eliminating the need to include here everything
149 * in "/usr/include".
150 */
151
152
Roland McGrathee36ce12004-09-04 03:53:10 +0000153static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000154#include "errnoent.h"
155};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200156static const char *const signalent0[] = {
157#include "signalent.h"
158};
159static const struct ioctlent ioctlent0[] = {
160#include "ioctlent.h"
161};
162enum { nsyscalls0 = ARRAY_SIZE(sysent0) };
163enum { nerrnos0 = ARRAY_SIZE(errnoent0) };
164enum { nsignals0 = ARRAY_SIZE(signalent0) };
165enum { nioctlents0 = ARRAY_SIZE(ioctlent0) };
166int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000167
168#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000169static const char *const errnoent1[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000170#include "errnoent1.h"
171};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200172static const char *const signalent1[] = {
173#include "signalent1.h"
174};
175static const struct ioctlent ioctlent1[] = {
176#include "ioctlent1.h"
177};
178enum { nsyscalls1 = ARRAY_SIZE(sysent1) };
179enum { nerrnos1 = ARRAY_SIZE(errnoent1) };
180enum { nsignals1 = ARRAY_SIZE(signalent1) };
181enum { nioctlents1 = ARRAY_SIZE(ioctlent1) };
182int qual_flags1[MAX_QUALS];
183#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000184
185#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000186static const char *const errnoent2[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000187#include "errnoent2.h"
188};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200189static const char *const signalent2[] = {
190#include "signalent2.h"
191};
192static const struct ioctlent ioctlent2[] = {
193#include "ioctlent2.h"
194};
195enum { nsyscalls2 = ARRAY_SIZE(sysent2) };
196enum { nerrnos2 = ARRAY_SIZE(errnoent2) };
197enum { nsignals2 = ARRAY_SIZE(signalent2) };
198enum { nioctlents2 = ARRAY_SIZE(ioctlent2) };
199int qual_flags2[MAX_QUALS];
200#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000201
Denys Vlasenko39fca622011-08-20 02:12:33 +0200202
203const struct sysent *sysent;
Roland McGrathee36ce12004-09-04 03:53:10 +0000204const char *const *errnoent;
Denys Vlasenko39fca622011-08-20 02:12:33 +0200205const char *const *signalent;
206const struct ioctlent *ioctlent;
207int nsyscalls;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000208int nerrnos;
Denys Vlasenko39fca622011-08-20 02:12:33 +0200209int nsignals;
210int nioctlents;
211int *qual_flags;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000212
213int current_personality;
214
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000215#ifndef PERSONALITY0_WORDSIZE
216# define PERSONALITY0_WORDSIZE sizeof(long)
217#endif
218const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
219 PERSONALITY0_WORDSIZE,
220#if SUPPORTED_PERSONALITIES > 1
221 PERSONALITY1_WORDSIZE,
222#endif
223#if SUPPORTED_PERSONALITIES > 2
224 PERSONALITY2_WORDSIZE,
225#endif
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200226};
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000227
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200228void
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000229set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000230{
231 switch (personality) {
232 case 0:
233 errnoent = errnoent0;
234 nerrnos = nerrnos0;
235 sysent = sysent0;
236 nsyscalls = nsyscalls0;
237 ioctlent = ioctlent0;
238 nioctlents = nioctlents0;
239 signalent = signalent0;
240 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000241 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000242 break;
243
244#if SUPPORTED_PERSONALITIES >= 2
245 case 1:
246 errnoent = errnoent1;
247 nerrnos = nerrnos1;
248 sysent = sysent1;
249 nsyscalls = nsyscalls1;
250 ioctlent = ioctlent1;
251 nioctlents = nioctlents1;
252 signalent = signalent1;
253 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000254 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000255 break;
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200256#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000257
258#if SUPPORTED_PERSONALITIES >= 3
259 case 2:
260 errnoent = errnoent2;
261 nerrnos = nerrnos2;
262 sysent = sysent2;
263 nsyscalls = nsyscalls2;
264 ioctlent = ioctlent2;
265 nioctlents = nioctlents2;
266 signalent = signalent2;
267 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000268 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000269 break;
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200270#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000271 }
272
273 current_personality = personality;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000274}
275
Roland McGrathe10e62a2004-09-04 04:20:43 +0000276
Roland McGrath9797ceb2002-12-30 10:23:00 +0000277static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000278
Roland McGrathe10e62a2004-09-04 04:20:43 +0000279static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000280 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000281 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000282 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000283 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000284} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000285 { QUAL_TRACE, "trace", qual_syscall, "system call" },
286 { QUAL_TRACE, "t", qual_syscall, "system call" },
287 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
288 { QUAL_ABBREV, "a", qual_syscall, "system call" },
289 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
290 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
291 { QUAL_RAW, "raw", qual_syscall, "system call" },
292 { QUAL_RAW, "x", qual_syscall, "system call" },
293 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
294 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
295 { QUAL_SIGNAL, "s", qual_signal, "signal" },
296 { QUAL_FAULT, "fault", qual_fault, "fault" },
297 { QUAL_FAULT, "faults", qual_fault, "fault" },
298 { QUAL_FAULT, "m", qual_fault, "fault" },
299 { QUAL_READ, "read", qual_desc, "descriptor" },
300 { QUAL_READ, "reads", qual_desc, "descriptor" },
301 { QUAL_READ, "r", qual_desc, "descriptor" },
302 { QUAL_WRITE, "write", qual_desc, "descriptor" },
303 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
304 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000305 { 0, NULL, NULL, NULL },
306};
307
Roland McGrath9797ceb2002-12-30 10:23:00 +0000308static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000309qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000310{
Roland McGrath138c6a32006-01-12 09:50:49 +0000311 if (pers == 0 || pers < 0) {
312 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000313 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000314 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000315 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000316 }
317
318#if SUPPORTED_PERSONALITIES >= 2
319 if (pers == 1 || pers < 0) {
320 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000321 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000322 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000323 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000324 }
325#endif /* SUPPORTED_PERSONALITIES >= 2 */
326
327#if SUPPORTED_PERSONALITIES >= 3
328 if (pers == 2 || pers < 0) {
329 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000330 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000331 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000332 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000333 }
334#endif /* SUPPORTED_PERSONALITIES >= 3 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000335}
336
337static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000338qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000339{
340 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000341 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000342
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000343 if (isdigit((unsigned char)*s)) {
344 int i = atoi(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000345 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000346 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000347 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000348 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000349 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000350 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000351 if (strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000352 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000353 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000354 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000355
356#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000357 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000358 if (strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000359 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000360 rc = 0;
361 }
362#endif /* SUPPORTED_PERSONALITIES >= 2 */
363
364#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000365 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000366 if (strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000367 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000368 rc = 0;
369 }
370#endif /* SUPPORTED_PERSONALITIES >= 3 */
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000371
Roland McGrathfe6b3522005-02-02 04:40:11 +0000372 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000373}
374
375static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000376qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000377{
378 int i;
379 char buf[32];
380
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000381 if (isdigit((unsigned char)*s)) {
382 int signo = atoi(s);
383 if (signo < 0 || signo >= MAX_QUALS)
384 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000385 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000386 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000387 }
Roland McGrathd62b6712004-03-02 06:52:01 +0000388 if (strlen(s) >= sizeof buf)
Roland McGrathfe6b3522005-02-02 04:40:11 +0000389 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000390 strcpy(buf, s);
391 s = buf;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000392 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000393 s += 3;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000394 for (i = 0; i <= NSIG; i++)
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000395 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000396 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000397 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000398 }
Roland McGrath76421df2005-02-02 03:51:18 +0000399 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000400}
401
402static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000403qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000404{
405 return -1;
406}
407
408static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000409qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000410{
Roland McGrath48a035f2006-01-12 09:45:56 +0000411 if (isdigit((unsigned char)*s)) {
Roland McGrathfe6b3522005-02-02 04:40:11 +0000412 int desc = atoi(s);
413 if (desc < 0 || desc >= MAX_QUALS)
414 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000415 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000416 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000417 }
418 return -1;
419}
420
421static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000422lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000423{
424 if (strcmp(s, "file") == 0)
425 return TRACE_FILE;
426 if (strcmp(s, "ipc") == 0)
427 return TRACE_IPC;
428 if (strcmp(s, "network") == 0)
429 return TRACE_NETWORK;
430 if (strcmp(s, "process") == 0)
431 return TRACE_PROCESS;
432 if (strcmp(s, "signal") == 0)
433 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000434 if (strcmp(s, "desc") == 0)
435 return TRACE_DESC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000436 return -1;
437}
438
439void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000440qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000441{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000442 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000443 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000444 char *copy;
445 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000446 int i, n;
447
448 opt = &qual_options[0];
449 for (i = 0; (p = qual_options[i].option_name); i++) {
450 n = strlen(p);
451 if (strncmp(s, p, n) == 0 && s[n] == '=') {
452 opt = &qual_options[i];
453 s += n + 1;
454 break;
455 }
456 }
457 not = 0;
458 if (*s == '!') {
459 not = 1;
460 s++;
461 }
462 if (strcmp(s, "none") == 0) {
463 not = 1 - not;
464 s = "all";
465 }
466 if (strcmp(s, "all") == 0) {
467 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000468 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000469 }
470 return;
471 }
472 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000473 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000474 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200475 copy = strdup(s);
476 if (!copy) {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000477 fprintf(stderr, "out of memory\n");
478 exit(1);
479 }
480 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000481 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000482 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000483 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000484 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000485
486#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000487 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000488 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000489 qualify_one(i, opt->bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000490#endif /* SUPPORTED_PERSONALITIES >= 2 */
491
492#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000493 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000494 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000495 qualify_one(i, opt->bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000496#endif /* SUPPORTED_PERSONALITIES >= 3 */
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000497
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000498 continue;
499 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000500 if (opt->qualify(p, opt->bitflag, not)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000501 fprintf(stderr, "strace: invalid %s `%s'\n",
502 opt->argument_name, p);
503 exit(1);
504 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000505 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000506 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000507 return;
508}
509
510static void
Dmitry V. Levin65c1a812011-02-09 00:39:47 +0000511dumpio(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000512{
513 if (syserror(tcp))
514 return;
515 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
516 return;
Dmitry V. Levin65c1a812011-02-09 00:39:47 +0000517 if (tcp->scno < 0 || tcp->scno >= nsyscalls)
518 return;
519 if (sysent[tcp->scno].sys_func == printargs)
520 return;
521 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
522 if (sysent[tcp->scno].sys_func == sys_read ||
523 sysent[tcp->scno].sys_func == sys_pread ||
524 sysent[tcp->scno].sys_func == sys_pread64 ||
525 sysent[tcp->scno].sys_func == sys_recv ||
526 sysent[tcp->scno].sys_func == sys_recvfrom)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000527 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
Dmitry V. Levin65c1a812011-02-09 00:39:47 +0000528 else if (sysent[tcp->scno].sys_func == sys_readv)
529 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
530 return;
531 }
532 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
533 if (sysent[tcp->scno].sys_func == sys_write ||
534 sysent[tcp->scno].sys_func == sys_pwrite ||
535 sysent[tcp->scno].sys_func == sys_pwrite64 ||
536 sysent[tcp->scno].sys_func == sys_send ||
537 sysent[tcp->scno].sys_func == sys_sendto)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000538 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
Dmitry V. Levin65c1a812011-02-09 00:39:47 +0000539 else if (sysent[tcp->scno].sys_func == sys_writev)
Denys Vlasenkoadedb512008-12-30 18:47:55 +0000540 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
Dmitry V. Levin65c1a812011-02-09 00:39:47 +0000541 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000542 }
543}
544
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000545#ifndef FREEBSD
Wichert Akkerman8829a551999-06-11 13:18:40 +0000546enum subcall_style { shift_style, deref_style, mask_style, door_style };
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000547#else /* FREEBSD */
548enum subcall_style { shift_style, deref_style, mask_style, door_style, table_style };
549
550struct subcall {
551 int call;
552 int nsubcalls;
553 int subcalls[5];
554};
555
Roland McGratha4d48532005-06-08 20:45:28 +0000556static const struct subcall subcalls_table[] = {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000557 { SYS_shmsys, 5, { SYS_shmat, SYS_shmctl, SYS_shmdt, SYS_shmget, SYS_shmctl } },
John Hughes61eeb552001-03-06 15:51:53 +0000558#ifdef SYS_semconfig
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000559 { SYS_semsys, 4, { SYS___semctl, SYS_semget, SYS_semop, SYS_semconfig } },
John Hughes61eeb552001-03-06 15:51:53 +0000560#else
561 { SYS_semsys, 3, { SYS___semctl, SYS_semget, SYS_semop } },
562#endif
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000563 { SYS_msgsys, 4, { SYS_msgctl, SYS_msgget, SYS_msgsnd, SYS_msgrcv } },
564};
565#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000566
Denys Vlasenko8ba1cd72008-12-30 17:50:46 +0000567#if !(defined(LINUX) && ( defined(ALPHA) || defined(MIPS) || defined(__ARM_EABI__) ))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000568
Roland McGratha4d48532005-06-08 20:45:28 +0000569static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200570decode_subcall(struct tcb *tcp, int subcall, int nsubcalls, enum subcall_style style)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000571{
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000572 unsigned long addr, mask;
Michal Ludvig10a88d02002-10-07 14:31:00 +0000573 int i;
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000574 int size = personality_wordsize[current_personality];
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000575
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000576 switch (style) {
577 case shift_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000578 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
579 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000580 tcp->scno = subcall + tcp->u_arg[0];
581 if (sysent[tcp->scno].nargs != -1)
582 tcp->u_nargs = sysent[tcp->scno].nargs;
583 else
584 tcp->u_nargs--;
585 for (i = 0; i < tcp->u_nargs; i++)
586 tcp->u_arg[i] = tcp->u_arg[i + 1];
587 break;
588 case deref_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000589 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
590 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000591 tcp->scno = subcall + tcp->u_arg[0];
592 addr = tcp->u_arg[1];
593 for (i = 0; i < sysent[tcp->scno].nargs; i++) {
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000594 if (size == sizeof(int)) {
595 unsigned int arg;
596 if (umove(tcp, addr, &arg) < 0)
597 arg = 0;
598 tcp->u_arg[i] = arg;
599 }
600 else if (size == sizeof(long)) {
601 unsigned long arg;
602 if (umove(tcp, addr, &arg) < 0)
603 arg = 0;
604 tcp->u_arg[i] = arg;
605 }
606 else
607 abort();
608 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000609 }
610 tcp->u_nargs = sysent[tcp->scno].nargs;
611 break;
612 case mask_style:
613 mask = (tcp->u_arg[0] >> 8) & 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000614 for (i = 0; mask; i++)
615 mask >>= 1;
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000616 if (i >= nsubcalls)
617 return;
618 tcp->u_arg[0] &= 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000619 tcp->scno = subcall + i;
620 if (sysent[tcp->scno].nargs != -1)
621 tcp->u_nargs = sysent[tcp->scno].nargs;
622 break;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000623 case door_style:
624 /*
625 * Oh, yuck. The call code is the *sixth* argument.
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000626 * (don't you mean the *last* argument? - JH)
Wichert Akkerman8829a551999-06-11 13:18:40 +0000627 */
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000628 if (tcp->u_arg[5] < 0 || tcp->u_arg[5] >= nsubcalls)
629 return;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000630 tcp->scno = subcall + tcp->u_arg[5];
631 if (sysent[tcp->scno].nargs != -1)
632 tcp->u_nargs = sysent[tcp->scno].nargs;
633 else
634 tcp->u_nargs--;
635 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000636#ifdef FREEBSD
637 case table_style:
Dmitry V. Levinfcda7a52011-06-13 21:58:43 +0000638 for (i = 0; i < ARRAY_SIZE(subcalls_table); i++)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000639 if (subcalls_table[i].call == tcp->scno) break;
Dmitry V. Levinfcda7a52011-06-13 21:58:43 +0000640 if (i < ARRAY_SIZE(subcalls_table) &&
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000641 tcp->u_arg[0] >= 0 && tcp->u_arg[0] < subcalls_table[i].nsubcalls) {
642 tcp->scno = subcalls_table[i].subcalls[tcp->u_arg[0]];
643 for (i = 0; i < tcp->u_nargs; i++)
644 tcp->u_arg[i] = tcp->u_arg[i + 1];
645 }
646 break;
647#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000648 }
649}
650#endif
651
652struct tcb *tcp_last = NULL;
653
654static int
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000655internal_syscall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000656{
657 /*
658 * We must always trace a few critical system calls in order to
659 * correctly support following forks in the presence of tracing
660 * qualifiers.
661 */
Denys Vlasenkoa7949742011-08-21 17:26:55 +0200662 int (*func)();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000663
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000664 if (tcp->scno < 0 || tcp->scno >= nsyscalls)
665 return 0;
666
667 func = sysent[tcp->scno].sys_func;
668
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000669 if ( sys_fork == func
670#if defined(FREEBSD) || defined(LINUX) || defined(SUNOS4)
671 || sys_vfork == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000672#endif
Dmitry V. Levin257e1572009-12-26 17:55:24 +0000673#ifdef LINUX
674 || sys_clone == func
675#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000676#if UNIXWARE > 2
677 || sys_rfork == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000678#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000679 )
680 return internal_fork(tcp);
681
Denys Vlasenkoa7949742011-08-21 17:26:55 +0200682#if defined SUNOS4 || (defined LINUX && defined TCB_WAITEXECVE)
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000683 if ( sys_execve == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +0200684# if defined(SPARC) || defined(SPARC64) || defined(SUNOS4)
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000685 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +0200686# endif
687# if UNIXWARE > 2
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000688 || sys_rexecve == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +0200689# endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000690 )
691 return internal_exec(tcp);
Denys Vlasenkoa7949742011-08-21 17:26:55 +0200692#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000693
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000694 return 0;
695}
696
Wichert Akkermanc7926982000-04-10 22:22:31 +0000697
698#ifdef LINUX
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200699# if defined (I386)
700static long eax;
701# elif defined (IA64)
702long r8, r10, psr; /* TODO: make static? */
703long ia32 = 0; /* not static */
704# elif defined (POWERPC)
705static long result, flags;
706# elif defined (M68K)
707static long d0;
708# elif defined(BFIN)
709static long r0;
710# elif defined (ARM)
711static struct pt_regs regs;
712# elif defined (ALPHA)
713static long r0;
714static long a3;
715# elif defined(AVR32)
716static struct pt_regs regs;
717# elif defined (SPARC) || defined (SPARC64)
718static struct pt_regs regs;
719static unsigned long trap;
720# elif defined(LINUX_MIPSN32)
721static long long a3;
722static long long r2;
723# elif defined(MIPS)
724static long a3;
725static long r2;
726# elif defined(S390) || defined(S390X)
727static long gpr2;
728static long pc;
729static long syscall_mode;
730# elif defined(HPPA)
731static long r28;
732# elif defined(SH)
733static long r0;
734# elif defined(SH64)
735static long r9;
736# elif defined(X86_64)
737static long rax;
738# elif defined(CRISV10) || defined(CRISV32)
739static long r10;
740# elif defined(MICROBLAZE)
741static long r3;
742# endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000743#endif /* LINUX */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000744#ifdef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200745struct reg regs; /* TODO: make static? */
Roland McGrath761b5d72002-12-15 23:58:31 +0000746#endif /* FREEBSD */
Wichert Akkermanc7926982000-04-10 22:22:31 +0000747
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200748/* Returns:
749 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
750 * 1: ok, continue in trace_syscall().
751 * other: error, trace_syscall() should print error indicator
752 * ("????" etc) and bail out.
753 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000754int
Denys Vlasenkofb036672009-01-23 16:30:26 +0000755get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000756{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000757 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000758
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000759#ifdef LINUX
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000760# if defined(S390) || defined(S390X)
Roland McGrath96dc5142003-01-20 10:23:04 +0000761 if (tcp->flags & TCB_WAITEXECVE) {
762 /*
763 * When the execve system call completes successfully, the
764 * new process still has -ENOSYS (old style) or __NR_execve
765 * (new style) in gpr2. We cannot recover the scno again
766 * by disassembly, because the image that executed the
767 * syscall is gone now. Fortunately, we don't want it. We
768 * leave the flag set so that syscall_fixup can fake the
769 * result.
770 */
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200771 if (exiting(tcp))
Roland McGrath96dc5142003-01-20 10:23:04 +0000772 return 1;
773 /*
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200774 * This is the post-execve SIGTRAP. We cannot try to read
Roland McGrath96dc5142003-01-20 10:23:04 +0000775 * the system call here either.
776 */
777 tcp->flags &= ~TCB_WAITEXECVE;
778 return 0;
779 }
Roland McGrath2f924ca2003-06-26 22:23:28 +0000780
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000781 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200782 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000783
784 if (syscall_mode != -ENOSYS) {
785 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000786 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000787 */
788 scno = syscall_mode;
789 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000790 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000791 * Old style of "passing" the scno via the SVC instruction.
792 */
793
794 long opcode, offset_reg, tmp;
795 void * svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200796 static const int gpr_offset[16] = {
797 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
798 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
799 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
800 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
801 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000802
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000803 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000804 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000805 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000806 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000807 if (errno) {
808 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000809 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000810 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000811
812 /*
813 * We have to check if the SVC got executed directly or via an
814 * EXECUTE instruction. In case of EXECUTE it is necessary to do
815 * instruction decoding to derive the system call number.
816 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
817 * so that this doesn't work if a SVC opcode is part of an EXECUTE
818 * opcode. Since there is no way to find out the opcode size this
819 * is the best we can do...
820 */
821
822 if ((opcode & 0xff00) == 0x0a00) {
823 /* SVC opcode */
824 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000825 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000826 else {
827 /* SVC got executed by EXECUTE instruction */
828
829 /*
830 * Do instruction decoding of EXECUTE. If you really want to
831 * understand this, read the Principles of Operations.
832 */
833 svc_addr = (void *) (opcode & 0xfff);
834
835 tmp = 0;
836 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000837 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000838 return -1;
839 svc_addr += tmp;
840
841 tmp = 0;
842 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000843 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000844 return -1;
845 svc_addr += tmp;
846
Denys Vlasenkofb036672009-01-23 16:30:26 +0000847 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000848 if (errno)
849 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000850# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000851 scno >>= 48;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000852# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000853 scno >>= 16;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000854# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000855 tmp = 0;
856 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000857 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000858 return -1;
859
860 scno = (scno | tmp) & 0xff;
861 }
862 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000863# elif defined (POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000864 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000865 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200866 if (entering(tcp)) {
867 /* Check if this is the post-execve SIGTRAP. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000868 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
869 tcp->flags &= ~TCB_WAITEXECVE;
870 return 0;
871 }
872 }
Andreas Schwabd69fa492010-07-12 21:39:57 +0200873
874# ifdef POWERPC64
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200875 if (entering(tcp)) {
Denys Vlasenkodeec74e2011-08-20 00:03:10 +0200876 /* TODO: speed up strace by not doing this at every syscall.
877 * We only need to do it after execve.
878 */
879 int currpers;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200880 long val;
881 int pid = tcp->pid;
882
883 /* Check for 64/32 bit mode. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200884 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
Andreas Schwabd69fa492010-07-12 21:39:57 +0200885 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 */
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200909 if (entering(tcp)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000910 scno = regs.r8;
911
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200912 /* Check if this is the post-execve SIGTRAP. */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000913 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
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200928 if (entering(tcp)) {
Denys Vlasenkodeec74e2011-08-20 00:03:10 +0200929 /* TODO: speed up strace by not doing this at every syscall.
930 * We only need to do it after execve.
931 */
932 int currpers;
Michal Ludvig0e035502002-09-23 15:41:01 +0000933 long val;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000934 int pid = tcp->pid;
Michal Ludvig0e035502002-09-23 15:41:01 +0000935
936 /* Check CS register value. On x86-64 linux it is:
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200937 * 0x33 for long mode (64 bit)
938 * 0x23 for compatibility mode (32 bit)
Roland McGrath761b5d72002-12-15 23:58:31 +0000939 * It takes only one ptrace and thus doesn't need
Michal Ludvig0e035502002-09-23 15:41:01 +0000940 * to be cached.
941 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000942 if (upeek(tcp, 8*CS, &val) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +0000943 return -1;
Denys Vlasenko8236f252009-01-02 18:10:08 +0000944 switch (val) {
Michal Ludvig0e035502002-09-23 15:41:01 +0000945 case 0x23: currpers = 1; break;
946 case 0x33: currpers = 0; break;
947 default:
948 fprintf(stderr, "Unknown value CS=0x%02X while "
949 "detecting personality of process "
950 "PID=%d\n", (int)val, pid);
951 currpers = current_personality;
952 break;
953 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000954# if 0
Michal Ludvig0e035502002-09-23 15:41:01 +0000955 /* This version analyzes the opcode of a syscall instruction.
956 * (int 0x80 on i386 vs. syscall on x86-64)
957 * It works, but is too complicated.
958 */
959 unsigned long val, rip, i;
960
Denys Vlasenko8236f252009-01-02 18:10:08 +0000961 if (upeek(tcp, 8*RIP, &rip) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +0000962 perror("upeek(RIP)");
Roland McGrath761b5d72002-12-15 23:58:31 +0000963
Michal Ludvig0e035502002-09-23 15:41:01 +0000964 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
Denys Vlasenko8236f252009-01-02 18:10:08 +0000965 rip -= 2;
Michal Ludvig0e035502002-09-23 15:41:01 +0000966 errno = 0;
967
Denys Vlasenko8236f252009-01-02 18:10:08 +0000968 call = ptrace(PTRACE_PEEKTEXT, pid, (char *)rip, (char *)0);
Roland McGrath761b5d72002-12-15 23:58:31 +0000969 if (errno)
Dmitry V. Levinbdafa1a2010-12-02 23:38:13 +0000970 fprintf(stderr, "ptrace_peektext failed: %s\n",
Michal Ludvig0e035502002-09-23 15:41:01 +0000971 strerror(errno));
Denys Vlasenko8236f252009-01-02 18:10:08 +0000972 switch (call & 0xffff) {
Michal Ludvig0e035502002-09-23 15:41:01 +0000973 /* x86-64: syscall = 0x0f 0x05 */
974 case 0x050f: currpers = 0; break;
975 /* i386: int 0x80 = 0xcd 0x80 */
976 case 0x80cd: currpers = 1; break;
977 default:
978 currpers = current_personality;
Roland McGrath761b5d72002-12-15 23:58:31 +0000979 fprintf(stderr,
Michal Ludvig0e035502002-09-23 15:41:01 +0000980 "Unknown syscall opcode (0x%04X) while "
981 "detecting personality of process "
982 "PID=%d\n", (int)call, pid);
983 break;
984 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000985# endif
Denys Vlasenko8236f252009-01-02 18:10:08 +0000986 if (currpers != current_personality) {
987 static const char *const names[] = {"64 bit", "32 bit"};
Michal Ludvig0e035502002-09-23 15:41:01 +0000988 set_personality(currpers);
Dmitry V. Levinbdafa1a2010-12-02 23:38:13 +0000989 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
Michal Ludvig0e035502002-09-23 15:41:01 +0000990 pid, names[current_personality]);
991 }
Roland McGrath761b5d72002-12-15 23:58:31 +0000992 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000993# elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000994# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200995 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000996 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200997 if (entering(tcp)) {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000998 if (ia32) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000999 if (upeek(tcp, PT_R1, &scno) < 0) /* orig eax */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001000 return -1;
1001 } else {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001002 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001003 return -1;
1004 }
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001005 /* Check if this is the post-execve SIGTRAP. */
Roland McGrathba954762003-03-05 06:29:06 +00001006 if (tcp->flags & TCB_WAITEXECVE) {
1007 tcp->flags &= ~TCB_WAITEXECVE;
1008 return 0;
1009 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001010 } else {
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001011 /* Syscall exit */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001012 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001013 return -1;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001014 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001015 return -1;
1016 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001017# elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001018 /*
1019 * Read complete register set in one go.
1020 */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001021 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +00001022 return -1;
1023
1024 /*
1025 * We only need to grab the syscall number on syscall entry.
1026 */
1027 if (regs.ARM_ip == 0) {
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001028 if (entering(tcp)) {
1029 /* Check if this is the post-execve SIGTRAP. */
Roland McGrath9bc63402007-11-01 21:42:18 +00001030 if (tcp->flags & TCB_WAITEXECVE) {
1031 tcp->flags &= ~TCB_WAITEXECVE;
1032 return 0;
1033 }
1034 }
1035
Roland McGrath0f87c492003-06-03 23:29:04 +00001036 /*
1037 * Note: we only deal with only 32-bit CPUs here.
1038 */
1039 if (regs.ARM_cpsr & 0x20) {
1040 /*
1041 * Get the Thumb-mode system call number
1042 */
1043 scno = regs.ARM_r7;
1044 } else {
1045 /*
1046 * Get the ARM-mode system call number
1047 */
1048 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +00001049 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +00001050 if (errno)
1051 return -1;
1052
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001053 /* FIXME: bogus check? it is already done on entering before,
1054 * so we never can see it here?
1055 */
Roland McGrath0f87c492003-06-03 23:29:04 +00001056 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
1057 tcp->flags &= ~TCB_WAITEXECVE;
1058 return 0;
1059 }
1060
Roland McGrathf691bd22006-04-25 07:34:41 +00001061 /* Handle the EABI syscall convention. We do not
1062 bother converting structures between the two
1063 ABIs, but basic functionality should work even
1064 if strace and the traced program have different
1065 ABIs. */
1066 if (scno == 0xef000000) {
1067 scno = regs.ARM_r7;
1068 } else {
1069 if ((scno & 0x0ff00000) != 0x0f900000) {
1070 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1071 scno);
1072 return -1;
1073 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001074
Roland McGrathf691bd22006-04-25 07:34:41 +00001075 /*
1076 * Fixup the syscall number
1077 */
1078 scno &= 0x000fffff;
1079 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001080 }
Roland McGrath56703312008-05-20 01:35:55 +00001081 if (scno & 0x0f0000) {
1082 /*
1083 * Handle ARM specific syscall
1084 */
1085 set_personality(1);
1086 scno &= 0x0000ffff;
1087 } else
1088 set_personality(0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001089
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001090 if (exiting(tcp)) {
1091 fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
Roland McGrath0f87c492003-06-03 23:29:04 +00001092 tcp->flags &= ~TCB_INSYSCALL;
1093 }
1094 } else {
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001095 if (entering(tcp)) {
1096 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
Roland McGrath0f87c492003-06-03 23:29:04 +00001097 tcp->flags |= TCB_INSYSCALL;
1098 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001099 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001100# elif defined (M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001101 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001102 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001103# elif defined (LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001104 unsigned long long regs[38];
1105
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001106 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001107 return -1;
1108 a3 = regs[REG_A3];
1109 r2 = regs[REG_V0];
1110
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001111 if (entering(tcp)) {
Roland McGrath542c2c62008-05-20 01:11:56 +00001112 scno = r2;
1113
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001114 /* Check if this is the post-execve SIGTRAP. */
Roland McGrath542c2c62008-05-20 01:11:56 +00001115 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1116 tcp->flags &= ~TCB_WAITEXECVE;
1117 return 0;
1118 }
1119
1120 if (scno < 0 || scno > nsyscalls) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001121 if (a3 == 0 || a3 == -1) {
1122 if (debug)
1123 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001124 return 0;
1125 }
1126 }
1127 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001128# elif defined (MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001129 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001130 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001131 if (entering(tcp)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001132 if (upeek(tcp, REG_V0, &scno) < 0)
1133 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001134
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001135 /* Check if this is the post-execve SIGTRAP. */
Roland McGrath542c2c62008-05-20 01:11:56 +00001136 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1137 tcp->flags &= ~TCB_WAITEXECVE;
1138 return 0;
1139 }
1140
Wichert Akkermanf90da011999-10-31 21:15:38 +00001141 if (scno < 0 || scno > nsyscalls) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001142 if (a3 == 0 || a3 == -1) {
1143 if (debug)
1144 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Wichert Akkermanf90da011999-10-31 21:15:38 +00001145 return 0;
1146 }
1147 }
1148 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001149 if (upeek(tcp, REG_V0, &r2) < 0)
1150 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001151 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001152# elif defined (ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001153 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154 return -1;
1155
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001156 if (entering(tcp)) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001157 if (upeek(tcp, REG_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001158 return -1;
1159
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001160 /* Check if this is the post-execve SIGTRAP. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001161 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1162 tcp->flags &= ~TCB_WAITEXECVE;
1163 return 0;
1164 }
1165
1166 /*
1167 * Do some sanity checks to figure out if it's
1168 * really a syscall entry
1169 */
1170 if (scno < 0 || scno > nsyscalls) {
1171 if (a3 == 0 || a3 == -1) {
1172 if (debug)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001173 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001174 return 0;
1175 }
1176 }
1177 }
1178 else {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001179 if (upeek(tcp, REG_R0, &r0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001180 return -1;
1181 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001182# elif defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001183 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001184 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001185 return -1;
1186
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001187 /* If we are entering, then disassemble the syscall trap. */
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001188 if (entering(tcp)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001189 /* Retrieve the syscall trap instruction. */
1190 errno = 0;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001191# if defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001192 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001193 trap >>= 32;
Mike Frysinger8566c502009-10-12 11:05:14 -04001194# else
1195 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001196# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001197 if (errno)
1198 return -1;
1199
1200 /* Disassemble the trap to see what personality to use. */
1201 switch (trap) {
1202 case 0x91d02010:
1203 /* Linux/SPARC syscall trap. */
1204 set_personality(0);
1205 break;
Wichert Akkermandacfb6e1999-06-03 14:21:07 +00001206 case 0x91d0206d:
1207 /* Linux/SPARC64 syscall trap. */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001208 set_personality(2);
1209 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001210 case 0x91d02000:
1211 /* SunOS syscall trap. (pers 1) */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001212 fprintf(stderr, "syscall: SunOS no support\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001213 return -1;
1214 case 0x91d02008:
1215 /* Solaris 2.x syscall trap. (per 2) */
1216 set_personality(1);
Roland McGrath761b5d72002-12-15 23:58:31 +00001217 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001218 case 0x91d02009:
1219 /* NetBSD/FreeBSD syscall trap. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001220 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001221 return -1;
1222 case 0x91d02027:
1223 /* Solaris 2.x gettimeofday */
1224 set_personality(1);
1225 break;
1226 default:
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001227 /* Check if this is the post-execve SIGTRAP. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001228 if (tcp->flags & TCB_WAITEXECVE) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001229 tcp->flags &= ~TCB_WAITEXECVE;
1230 return 0;
1231 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001232# if defined (SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001233 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001234# else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001235 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001236# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001237 return -1;
1238 }
1239
1240 /* Extract the system call number from the registers. */
1241 if (trap == 0x91d02027)
1242 scno = 156;
1243 else
Mike Frysinger8566c502009-10-12 11:05:14 -04001244 scno = regs.u_regs[U_REG_G1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001245 if (scno == 0) {
Mike Frysinger8566c502009-10-12 11:05:14 -04001246 scno = regs.u_regs[U_REG_O0];
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001247 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 +00001248 }
1249 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001250# elif defined(HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001251 if (upeek(tcp, PT_GR20, &scno) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001252 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001253 if (entering(tcp)) {
1254 /* Check if this is the post-execve SIGTRAP. */
1255 if (tcp->flags & TCB_WAITEXECVE) {
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001256 tcp->flags &= ~TCB_WAITEXECVE;
1257 return 0;
1258 }
1259 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001260# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001261 /*
1262 * In the new syscall ABI, the system call number is in R3.
1263 */
1264 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1265 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001266
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001267 if (scno < 0) {
1268 /* Odd as it may seem, a glibc bug has been known to cause
1269 glibc to issue bogus negative syscall numbers. So for
1270 our purposes, make strace print what it *should* have been */
1271 long correct_scno = (scno & 0xff);
1272 if (debug)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001273 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001274 "Detected glibc bug: bogus system call"
1275 " number = %ld, correcting to %ld\n",
1276 scno,
1277 correct_scno);
1278 scno = correct_scno;
1279 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00001280
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001281 if (entering(tcp)) {
1282 /* Check if this is the post-execve SIGTRAP. */
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001283 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1284 tcp->flags &= ~TCB_WAITEXECVE;
1285 return 0;
1286 }
1287 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001288# elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001289 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001290 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001291 scno &= 0xFFFF;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001292
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001293 if (entering(tcp)) {
1294 /* Check if this is the post-execve SIGTRAP. */
Roland McGrathe1e584b2003-06-02 19:18:58 +00001295 if (tcp->flags & TCB_WAITEXECVE) {
1296 tcp->flags &= ~TCB_WAITEXECVE;
1297 return 0;
1298 }
1299 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001300# elif defined(CRISV10) || defined(CRISV32)
1301 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1302 return -1;
Chris Metcalfc8c66982009-12-28 10:00:15 -05001303# elif defined(TILE)
1304 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1305 return -1;
1306
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001307 if (entering(tcp)) {
1308 /* Check if this is the post-execve SIGTRAP. */
Chris Metcalfc8c66982009-12-28 10:00:15 -05001309 if (tcp->flags & TCB_WAITEXECVE) {
1310 tcp->flags &= ~TCB_WAITEXECVE;
1311 return 0;
1312 }
1313 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001314# elif defined(MICROBLAZE)
1315 if (upeek(tcp, 0, &scno) < 0)
1316 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001317# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001318#endif /* LINUX */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001319
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001320#ifdef SUNOS4
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001321 if (upeek(tcp, uoff(u_arg[7]), &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001322 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001323#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001324 /* new syscall ABI returns result in R0 */
1325 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1326 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001327#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001328 /* ABI defines result returned in r9 */
1329 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1330 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001331#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001332
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001333#ifdef USE_PROCFS
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001334# ifdef HAVE_PR_SYSCALL
John Hughes25299712001-03-06 10:10:06 +00001335 scno = tcp->status.PR_SYSCALL;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001336# else
1337# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001338 scno = tcp->status.PR_WHAT;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001339# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001340 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001341 perror("pread");
1342 return -1;
1343 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001344 switch (regs.r_eax) {
1345 case SYS_syscall:
1346 case SYS___syscall:
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001347 pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int));
1348 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001349 default:
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001350 scno = regs.r_eax;
1351 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001352 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001353# endif /* FREEBSD */
1354# endif /* !HAVE_PR_SYSCALL */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001355#endif /* USE_PROCFS */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001356
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001357 if (entering(tcp))
Wichert Akkerman5ae21ea2000-05-01 01:53:59 +00001358 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001359 return 1;
1360}
1361
Pavel Machek4dc3b142000-02-01 17:58:41 +00001362
Roland McGrath17352792005-06-07 23:21:26 +00001363long
Dmitry V. Levinbd136452011-02-18 23:19:47 +00001364known_scno(struct tcb *tcp)
Roland McGrath17352792005-06-07 23:21:26 +00001365{
1366 long scno = tcp->scno;
Dmitry V. Levinbd136452011-02-18 23:19:47 +00001367#if SUPPORTED_PERSONALITIES > 1
Roland McGrath17352792005-06-07 23:21:26 +00001368 if (scno >= 0 && scno < nsyscalls && sysent[scno].native_scno != 0)
1369 scno = sysent[scno].native_scno;
1370 else
Dmitry V. Levinbd136452011-02-18 23:19:47 +00001371#endif
Roland McGrath17352792005-06-07 23:21:26 +00001372 scno += NR_SYSCALL_BASE;
1373 return scno;
1374}
1375
Roland McGratheb9e2e82009-06-02 16:49:22 -07001376/* Called in trace_syscall() at each syscall entry and exit.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001377 * Returns:
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001378 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
Roland McGratheb9e2e82009-06-02 16:49:22 -07001379 * 1: ok, continue in trace_syscall().
1380 * other: error, trace_syscall() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001381 * ("????" etc) and bail out.
1382 */
Roland McGratha4d48532005-06-08 20:45:28 +00001383static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001384syscall_fixup(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001385{
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001386#ifdef USE_PROCFS
Roland McGrath17352792005-06-07 23:21:26 +00001387 int scno = known_scno(tcp);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001388
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001389 if (entering(tcp)) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001390 if (tcp->status.PR_WHY != PR_SYSENTRY) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001391 if (
1392 scno == SYS_fork
1393#ifdef SYS_vfork
1394 || scno == SYS_vfork
1395#endif /* SYS_vfork */
John Hughes4e36a812001-04-18 15:11:51 +00001396#ifdef SYS_fork1
1397 || scno == SYS_fork1
1398#endif /* SYS_fork1 */
1399#ifdef SYS_forkall
1400 || scno == SYS_forkall
1401#endif /* SYS_forkall */
1402#ifdef SYS_rfork1
1403 || scno == SYS_rfork1
1404#endif /* SYS_fork1 */
1405#ifdef SYS_rforkall
1406 || scno == SYS_rforkall
1407#endif /* SYS_rforkall */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001408 ) {
1409 /* We are returning in the child, fake it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001410 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001411 trace_syscall(tcp);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001412 tcp->status.PR_WHY = PR_SYSEXIT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001413 }
1414 else {
1415 fprintf(stderr, "syscall: missing entry\n");
1416 tcp->flags |= TCB_INSYSCALL;
1417 }
1418 }
1419 }
1420 else {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001421 if (tcp->status.PR_WHY != PR_SYSEXIT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001422 fprintf(stderr, "syscall: missing exit\n");
1423 tcp->flags &= ~TCB_INSYSCALL;
1424 }
1425 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001426#endif /* USE_PROCFS */
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001427
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001428#ifdef SUNOS4
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001429 if (entering(tcp)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001430 if (scno == 0) {
1431 fprintf(stderr, "syscall: missing entry\n");
1432 tcp->flags |= TCB_INSYSCALL;
1433 }
1434 }
1435 else {
1436 if (scno != 0) {
1437 if (debug) {
1438 /*
1439 * This happens when a signal handler
1440 * for a signal which interrupted a
1441 * a system call makes another system call.
1442 */
1443 fprintf(stderr, "syscall: missing exit\n");
1444 }
1445 tcp->flags &= ~TCB_INSYSCALL;
1446 }
1447 }
1448#endif /* SUNOS4 */
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001449
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001450#ifdef LINUX
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001451 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001452#if defined (I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001453 if (upeek(tcp, 4*EAX, &eax) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001454 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001455 if (eax != -ENOSYS && entering(tcp)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001456 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001457 fprintf(stderr, "not a syscall entry (eax = %ld)\n", eax);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001458 return 0;
1459 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001460#elif defined (X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001461 if (upeek(tcp, 8*RAX, &rax) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00001462 return -1;
Roland McGrath998fac72004-06-23 01:40:45 +00001463 if (current_personality == 1)
1464 rax = (long int)(int)rax; /* sign extend from 32 bits */
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001465 if (rax != -ENOSYS && entering(tcp)) {
Michal Ludvig0e035502002-09-23 15:41:01 +00001466 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001467 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
Michal Ludvig0e035502002-09-23 15:41:01 +00001468 return 0;
1469 }
Michal Ludvig10a88d02002-10-07 14:31:00 +00001470#elif defined (S390) || defined (S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001471 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001472 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001473 if (syscall_mode != -ENOSYS)
1474 syscall_mode = tcp->scno;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001475 if (gpr2 != syscall_mode && entering(tcp)) {
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001476 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001477 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001478 return 0;
1479 }
Roland McGrath96dc5142003-01-20 10:23:04 +00001480 else if (((tcp->flags & (TCB_INSYSCALL|TCB_WAITEXECVE))
1481 == (TCB_INSYSCALL|TCB_WAITEXECVE))
1482 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1483 /*
1484 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1485 * flag set for the post-execve SIGTRAP to see and reset.
1486 */
1487 gpr2 = 0;
1488 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001489#elif defined (POWERPC)
1490# define SO_MASK 0x10000000
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001491 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001492 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001493 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &result) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001494 return -1;
1495 if (flags & SO_MASK)
1496 result = -result;
1497#elif defined (M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001498 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001499 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001500 if (d0 != -ENOSYS && entering(tcp)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001501 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001502 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001503 return 0;
1504 }
1505#elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001506 /*
1507 * Nothing required
1508 */
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001509#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001510 if (upeek(tcp, PT_R0, &r0) < 0)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001511 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001512#elif defined (HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001513 if (upeek(tcp, PT_GR28, &r28) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001514 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001515#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001516 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001517 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001518 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001519 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001520 if (ia32 && r8 != -ENOSYS && entering(tcp)) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001521 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001522 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001523 return 0;
1524 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001525#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001526 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001527 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001528 if (r10 != -ENOSYS && entering(tcp)) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001529 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001530 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001531 return 0;
1532 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001533#elif defined(MICROBLAZE)
1534 if (upeek(tcp, 3 * 4, &r3) < 0)
1535 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001536 if (r3 != -ENOSYS && entering(tcp)) {
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001537 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001538 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001539 return 0;
1540 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001541#endif
1542#endif /* LINUX */
Pavel Machek4dc3b142000-02-01 17:58:41 +00001543 return 1;
1544}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001545
Roland McGrathc1e45922008-05-27 23:18:29 +00001546#ifdef LINUX
1547/*
1548 * Check the syscall return value register value for whether it is
1549 * a negated errno code indicating an error, or a success return value.
1550 */
1551static inline int
1552is_negated_errno(unsigned long int val)
1553{
1554 unsigned long int max = -(long int) nerrnos;
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001555# if SUPPORTED_PERSONALITIES > 1
Roland McGrathc1e45922008-05-27 23:18:29 +00001556 if (personality_wordsize[current_personality] < sizeof(val)) {
1557 val = (unsigned int) val;
1558 max = (unsigned int) max;
1559 }
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001560# endif
Roland McGrathc1e45922008-05-27 23:18:29 +00001561 return val > max;
1562}
1563#endif
1564
Roland McGratha4d48532005-06-08 20:45:28 +00001565static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001566get_error(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001567{
1568 int u_error = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001569#ifdef LINUX
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001570 int check_errno = 1;
1571 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
1572 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1573 check_errno = 0;
1574 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001575# if defined(S390) || defined(S390X)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001576 if (check_errno && is_negated_errno(gpr2)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001577 tcp->u_rval = -1;
1578 u_error = -gpr2;
1579 }
1580 else {
1581 tcp->u_rval = gpr2;
1582 u_error = 0;
1583 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001584# elif defined(I386)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001585 if (check_errno && is_negated_errno(eax)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001586 tcp->u_rval = -1;
1587 u_error = -eax;
1588 }
1589 else {
1590 tcp->u_rval = eax;
1591 u_error = 0;
1592 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001593# elif defined(X86_64)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001594 if (check_errno && is_negated_errno(rax)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001595 tcp->u_rval = -1;
1596 u_error = -rax;
1597 }
1598 else {
1599 tcp->u_rval = rax;
1600 u_error = 0;
1601 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001602# elif defined(IA64)
Roland McGrathc1e45922008-05-27 23:18:29 +00001603 if (ia32) {
1604 int err;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001605
Roland McGrathc1e45922008-05-27 23:18:29 +00001606 err = (int)r8;
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001607 if (check_errno && is_negated_errno(err)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001608 tcp->u_rval = -1;
1609 u_error = -err;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001610 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001611 else {
1612 tcp->u_rval = err;
1613 u_error = 0;
1614 }
1615 } else {
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001616 if (check_errno && r10) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001617 tcp->u_rval = -1;
1618 u_error = r8;
1619 } else {
1620 tcp->u_rval = r8;
1621 u_error = 0;
1622 }
1623 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001624# elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001625 if (check_errno && a3) {
1626 tcp->u_rval = -1;
1627 u_error = r2;
1628 } else {
1629 tcp->u_rval = r2;
1630 u_error = 0;
1631 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001632# elif defined(POWERPC)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001633 if (check_errno && is_negated_errno(result)) {
1634 tcp->u_rval = -1;
1635 u_error = -result;
1636 }
1637 else {
1638 tcp->u_rval = result;
1639 u_error = 0;
1640 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001641# elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001642 if (check_errno && is_negated_errno(d0)) {
1643 tcp->u_rval = -1;
1644 u_error = -d0;
1645 }
1646 else {
1647 tcp->u_rval = d0;
1648 u_error = 0;
1649 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001650# elif defined(ARM)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001651 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1652 tcp->u_rval = -1;
1653 u_error = -regs.ARM_r0;
1654 }
1655 else {
1656 tcp->u_rval = regs.ARM_r0;
1657 u_error = 0;
1658 }
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001659# elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001660 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1661 tcp->u_rval = -1;
1662 u_error = -regs.r12;
1663 }
1664 else {
1665 tcp->u_rval = regs.r12;
1666 u_error = 0;
1667 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001668# elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001669 if (check_errno && is_negated_errno(r0)) {
1670 tcp->u_rval = -1;
1671 u_error = -r0;
1672 } else {
1673 tcp->u_rval = r0;
1674 u_error = 0;
1675 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001676# elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001677 if (check_errno && a3) {
1678 tcp->u_rval = -1;
1679 u_error = r0;
1680 }
1681 else {
1682 tcp->u_rval = r0;
1683 u_error = 0;
1684 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001685# elif defined(SPARC)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001686 if (check_errno && regs.psr & PSR_C) {
1687 tcp->u_rval = -1;
1688 u_error = regs.u_regs[U_REG_O0];
1689 }
1690 else {
1691 tcp->u_rval = regs.u_regs[U_REG_O0];
1692 u_error = 0;
1693 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001694# elif defined(SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001695 if (check_errno && regs.tstate & 0x1100000000UL) {
1696 tcp->u_rval = -1;
1697 u_error = regs.u_regs[U_REG_O0];
1698 }
1699 else {
1700 tcp->u_rval = regs.u_regs[U_REG_O0];
1701 u_error = 0;
1702 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001703# elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001704 if (check_errno && is_negated_errno(r28)) {
1705 tcp->u_rval = -1;
1706 u_error = -r28;
1707 }
1708 else {
1709 tcp->u_rval = r28;
1710 u_error = 0;
1711 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001712# elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001713 /* interpret R0 as return value or error number */
1714 if (check_errno && is_negated_errno(r0)) {
1715 tcp->u_rval = -1;
1716 u_error = -r0;
1717 }
1718 else {
1719 tcp->u_rval = r0;
1720 u_error = 0;
1721 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001722# elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001723 /* interpret result as return value or error number */
1724 if (check_errno && is_negated_errno(r9)) {
1725 tcp->u_rval = -1;
1726 u_error = -r9;
1727 }
1728 else {
1729 tcp->u_rval = r9;
1730 u_error = 0;
1731 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001732# elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001733 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1734 tcp->u_rval = -1;
1735 u_error = -r10;
1736 }
1737 else {
1738 tcp->u_rval = r10;
1739 u_error = 0;
1740 }
Chris Metcalfc8c66982009-12-28 10:00:15 -05001741# elif defined(TILE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001742 long rval;
1743 /* interpret result as return value or error number */
1744 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1745 return -1;
1746 if (check_errno && rval < 0 && rval > -nerrnos) {
1747 tcp->u_rval = -1;
1748 u_error = -rval;
1749 }
1750 else {
1751 tcp->u_rval = rval;
1752 u_error = 0;
1753 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001754# elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001755 /* interpret result as return value or error number */
1756 if (check_errno && is_negated_errno(r3)) {
1757 tcp->u_rval = -1;
1758 u_error = -r3;
1759 }
1760 else {
1761 tcp->u_rval = r3;
1762 u_error = 0;
1763 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001764# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001765#endif /* LINUX */
1766#ifdef SUNOS4
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001767 /* get error code from user struct */
1768 if (upeek(tcp, uoff(u_error), &u_error) < 0)
1769 return -1;
1770 u_error >>= 24; /* u_error is a char */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001771
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001772 /* get system call return value */
1773 if (upeek(tcp, uoff(u_rval1), &tcp->u_rval) < 0)
1774 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001775#endif /* SUNOS4 */
1776#ifdef SVR4
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001777# ifdef SPARC
1778 /* Judicious guessing goes a long way. */
1779 if (tcp->status.pr_reg[R_PSR] & 0x100000) {
1780 tcp->u_rval = -1;
1781 u_error = tcp->status.pr_reg[R_O0];
1782 }
1783 else {
1784 tcp->u_rval = tcp->status.pr_reg[R_O0];
1785 u_error = 0;
1786 }
1787# endif /* SPARC */
1788# ifdef I386
1789 /* Wanna know how to kill an hour single-stepping? */
1790 if (tcp->status.PR_REG[EFL] & 0x1) {
1791 tcp->u_rval = -1;
1792 u_error = tcp->status.PR_REG[EAX];
1793 }
1794 else {
1795 tcp->u_rval = tcp->status.PR_REG[EAX];
1796# ifdef HAVE_LONG_LONG
1797 tcp->u_lrval =
1798 ((unsigned long long) tcp->status.PR_REG[EDX] << 32) +
1799 tcp->status.PR_REG[EAX];
1800# endif
1801 u_error = 0;
1802 }
1803# endif /* I386 */
1804# ifdef X86_64
1805 /* Wanna know how to kill an hour single-stepping? */
1806 if (tcp->status.PR_REG[EFLAGS] & 0x1) {
1807 tcp->u_rval = -1;
1808 u_error = tcp->status.PR_REG[RAX];
1809 }
1810 else {
1811 tcp->u_rval = tcp->status.PR_REG[RAX];
1812 u_error = 0;
1813 }
1814# endif /* X86_64 */
1815# ifdef MIPS
1816 if (tcp->status.pr_reg[CTX_A3]) {
1817 tcp->u_rval = -1;
1818 u_error = tcp->status.pr_reg[CTX_V0];
1819 }
1820 else {
1821 tcp->u_rval = tcp->status.pr_reg[CTX_V0];
1822 u_error = 0;
1823 }
1824# endif /* MIPS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001825#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001826#ifdef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001827 if (regs.r_eflags & PSL_C) {
1828 tcp->u_rval = -1;
1829 u_error = regs.r_eax;
1830 } else {
1831 tcp->u_rval = regs.r_eax;
1832 tcp->u_lrval =
1833 ((unsigned long long) regs.r_edx << 32) + regs.r_eax;
1834 u_error = 0;
1835 }
Roland McGrath761b5d72002-12-15 23:58:31 +00001836#endif /* FREEBSD */
Pavel Machek4dc3b142000-02-01 17:58:41 +00001837 tcp->u_error = u_error;
1838 return 1;
1839}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001840
Roland McGrathb69f81b2002-12-21 23:25:18 +00001841int
Denys Vlasenko12014262011-05-30 14:00:14 +02001842force_result(struct tcb *tcp, int error, long rval)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001843{
1844#ifdef LINUX
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001845# if defined(S390) || defined(S390X)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001846 gpr2 = error ? -error : rval;
Roland McGrathb69f81b2002-12-21 23:25:18 +00001847 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_GPR2, gpr2) < 0)
1848 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001849# elif defined(I386)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001850 eax = error ? -error : rval;
1851 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(EAX * 4), eax) < 0)
1852 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001853# elif defined(X86_64)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001854 rax = error ? -error : rval;
Roland McGrath998fac72004-06-23 01:40:45 +00001855 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(RAX * 8), rax) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001856 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001857# elif defined(IA64)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001858 if (ia32) {
1859 r8 = error ? -error : rval;
1860 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0)
1861 return -1;
1862 }
1863 else {
1864 if (error) {
1865 r8 = error;
1866 r10 = -1;
1867 }
1868 else {
1869 r8 = rval;
1870 r10 = 0;
1871 }
1872 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0 ||
1873 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R10), r10) < 0)
1874 return -1;
1875 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001876# elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001877 r0 = error ? -error : rval;
1878 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_R0, r0) < 0)
1879 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001880# elif defined(MIPS)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001881 if (error) {
1882 r2 = error;
1883 a3 = -1;
1884 }
1885 else {
1886 r2 = rval;
1887 a3 = 0;
1888 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001889 /* PTRACE_POKEUSER is OK even for n32 since rval is only a long. */
Roland McGrathb69f81b2002-12-21 23:25:18 +00001890 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1891 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), r2) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001892 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001893# elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001894 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001895 return -1;
1896 if (error) {
1897 flags |= SO_MASK;
1898 result = error;
1899 }
1900 else {
1901 flags &= ~SO_MASK;
1902 result = rval;
1903 }
Roland McGratheb285352003-01-14 09:59:00 +00001904 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_CCR), flags) < 0 ||
1905 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_R3), result) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001906 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001907# elif defined(M68K)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001908 d0 = error ? -error : rval;
1909 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_D0), d0) < 0)
1910 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001911# elif defined(ARM)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001912 regs.ARM_r0 = error ? -error : rval;
1913 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*0), regs.ARM_r0) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001914 return -1;
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001915# elif defined(AVR32)
1916 regs.r12 = error ? -error : rval;
1917 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_R12, regs.r12) < 0)
1918 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001919# elif defined(ALPHA)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001920 if (error) {
1921 a3 = -1;
1922 r0 = error;
1923 }
1924 else {
1925 a3 = 0;
1926 r0 = rval;
1927 }
1928 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1929 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R0), r0) < 0)
1930 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001931# elif defined(SPARC)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001932 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1933 return -1;
1934 if (error) {
Mike Frysinger8566c502009-10-12 11:05:14 -04001935 regs.psr |= PSR_C;
1936 regs.u_regs[U_REG_O0] = error;
Roland McGrathb69f81b2002-12-21 23:25:18 +00001937 }
1938 else {
Mike Frysinger8566c502009-10-12 11:05:14 -04001939 regs.psr &= ~PSR_C;
1940 regs.u_regs[U_REG_O0] = rval;
Roland McGrathb69f81b2002-12-21 23:25:18 +00001941 }
1942 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1943 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001944# elif defined(SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001945 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1946 return -1;
1947 if (error) {
Mike Frysinger8566c502009-10-12 11:05:14 -04001948 regs.tstate |= 0x1100000000UL;
1949 regs.u_regs[U_REG_O0] = error;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001950 }
1951 else {
Mike Frysinger8566c502009-10-12 11:05:14 -04001952 regs.tstate &= ~0x1100000000UL;
1953 regs.u_regs[U_REG_O0] = rval;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001954 }
1955 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1956 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001957# elif defined(HPPA)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001958 r28 = error ? -error : rval;
1959 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR28), r28) < 0)
1960 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001961# elif defined(SH)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001962 r0 = error ? -error : rval;
1963 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*REG_REG0), r0) < 0)
1964 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001965# elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001966 r9 = error ? -error : rval;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001967 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_GENERAL(9), r9) < 0)
1968 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001969# endif
Roland McGrathb69f81b2002-12-21 23:25:18 +00001970#endif /* LINUX */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001971
Roland McGrathb69f81b2002-12-21 23:25:18 +00001972#ifdef SUNOS4
Roland McGratheb9e2e82009-06-02 16:49:22 -07001973 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_error),
1974 error << 24) < 0 ||
1975 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_rval1), rval) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001976 return -1;
1977#endif /* SUNOS4 */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001978
Roland McGrathb69f81b2002-12-21 23:25:18 +00001979#ifdef SVR4
1980 /* XXX no clue */
1981 return -1;
1982#endif /* SVR4 */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001983
Roland McGrathb69f81b2002-12-21 23:25:18 +00001984#ifdef FREEBSD
1985 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001986 perror("pread");
1987 return -1;
1988 }
Roland McGrathb69f81b2002-12-21 23:25:18 +00001989 if (error) {
1990 regs.r_eflags |= PSL_C;
1991 regs.r_eax = error;
1992 }
1993 else {
1994 regs.r_eflags &= ~PSL_C;
1995 regs.r_eax = rval;
1996 }
1997 if (pwrite(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001998 perror("pwrite");
1999 return -1;
2000 }
Roland McGrathb69f81b2002-12-21 23:25:18 +00002001#endif /* FREEBSD */
2002
2003 /* All branches reach here on success (only). */
2004 tcp->u_error = error;
2005 tcp->u_rval = rval;
2006 return 0;
2007}
2008
Roland McGratha4d48532005-06-08 20:45:28 +00002009static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002010syscall_enter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002011{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002012#ifdef LINUX
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002013# if defined(S390) || defined(S390X)
2014 int i;
2015 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2016 tcp->u_nargs = sysent[tcp->scno].nargs;
2017 else
2018 tcp->u_nargs = MAX_ARGS;
2019 for (i = 0; i < tcp->u_nargs; i++) {
2020 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
2021 return -1;
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00002022 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002023# elif defined(ALPHA)
2024 int i;
2025 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2026 tcp->u_nargs = sysent[tcp->scno].nargs;
2027 else
2028 tcp->u_nargs = MAX_ARGS;
2029 for (i = 0; i < tcp->u_nargs; i++) {
2030 /* WTA: if scno is out-of-bounds this will bomb. Add range-check
2031 * for scno somewhere above here!
2032 */
2033 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
2034 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002035 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002036# elif defined(IA64)
2037 if (!ia32) {
2038 unsigned long *out0, cfm, sof, sol, i;
2039 long rbs_end;
2040 /* be backwards compatible with kernel < 2.4.4... */
2041# ifndef PT_RBS_END
2042# define PT_RBS_END PT_AR_BSP
2043# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002044
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002045 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
2046 return -1;
2047 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00002048 return -1;
2049
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002050 sof = (cfm >> 0) & 0x7f;
2051 sol = (cfm >> 7) & 0x7f;
2052 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
2053
2054 if (tcp->scno >= 0 && tcp->scno < nsyscalls
2055 && sysent[tcp->scno].nargs != -1)
2056 tcp->u_nargs = sysent[tcp->scno].nargs;
2057 else
2058 tcp->u_nargs = MAX_ARGS;
2059 for (i = 0; i < tcp->u_nargs; ++i) {
2060 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
2061 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
2062 return -1;
2063 }
2064 } else {
2065 int i;
2066
2067 if (/* EBX = out0 */
2068 upeek(tcp, PT_R11, (long *) &tcp->u_arg[0]) < 0
2069 /* ECX = out1 */
2070 || upeek(tcp, PT_R9, (long *) &tcp->u_arg[1]) < 0
2071 /* EDX = out2 */
2072 || upeek(tcp, PT_R10, (long *) &tcp->u_arg[2]) < 0
2073 /* ESI = out3 */
2074 || upeek(tcp, PT_R14, (long *) &tcp->u_arg[3]) < 0
2075 /* EDI = out4 */
2076 || upeek(tcp, PT_R15, (long *) &tcp->u_arg[4]) < 0
2077 /* EBP = out5 */
2078 || upeek(tcp, PT_R13, (long *) &tcp->u_arg[5]) < 0)
2079 return -1;
2080
2081 for (i = 0; i < 6; ++i)
2082 /* truncate away IVE sign-extension */
2083 tcp->u_arg[i] &= 0xffffffff;
2084
2085 if (tcp->scno >= 0 && tcp->scno < nsyscalls
2086 && sysent[tcp->scno].nargs != -1)
2087 tcp->u_nargs = sysent[tcp->scno].nargs;
2088 else
2089 tcp->u_nargs = 5;
2090 }
2091# elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
2092 /* N32 and N64 both use up to six registers. */
2093 unsigned long long regs[38];
2094 int i, nargs;
2095 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2096 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
2097 else
2098 nargs = tcp->u_nargs = MAX_ARGS;
2099
2100 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
2101 return -1;
2102
2103 for (i = 0; i < nargs; i++) {
2104 tcp->u_arg[i] = regs[REG_A0 + i];
2105# if defined(LINUX_MIPSN32)
2106 tcp->ext_arg[i] = regs[REG_A0 + i];
2107# endif
2108 }
2109# elif defined(MIPS)
2110 long sp;
2111 int i, nargs;
2112
2113 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2114 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
2115 else
2116 nargs = tcp->u_nargs = MAX_ARGS;
2117 if (nargs > 4) {
2118 if (upeek(tcp, REG_SP, &sp) < 0)
2119 return -1;
2120 for (i = 0; i < 4; i++) {
2121 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
2122 return -1;
2123 }
2124 umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]),
2125 (char *)(tcp->u_arg + 4));
2126 } else {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002127 for (i = 0; i < nargs; i++) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002128 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002129 return -1;
2130 }
2131 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002132# elif defined(POWERPC)
2133# ifndef PT_ORIG_R3
2134# define PT_ORIG_R3 34
2135# endif
2136 int i;
2137 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2138 tcp->u_nargs = sysent[tcp->scno].nargs;
2139 else
2140 tcp->u_nargs = MAX_ARGS;
2141 for (i = 0; i < tcp->u_nargs; i++) {
2142 if (upeek(tcp, (i==0) ?
2143 (sizeof(unsigned long) * PT_ORIG_R3) :
2144 ((i+PT_R3) * sizeof(unsigned long)),
2145 &tcp->u_arg[i]) < 0)
2146 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002147 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002148# elif defined(SPARC) || defined(SPARC64)
2149 int i;
2150 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2151 tcp->u_nargs = sysent[tcp->scno].nargs;
2152 else
2153 tcp->u_nargs = MAX_ARGS;
2154 for (i = 0; i < tcp->u_nargs; i++)
2155 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
2156# elif defined(HPPA)
2157 int i;
2158 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2159 tcp->u_nargs = sysent[tcp->scno].nargs;
2160 else
2161 tcp->u_nargs = MAX_ARGS;
2162 for (i = 0; i < tcp->u_nargs; i++) {
2163 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
2164 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002165 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002166# elif defined(ARM)
2167 int i;
2168 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2169 tcp->u_nargs = sysent[tcp->scno].nargs;
2170 else
2171 tcp->u_nargs = MAX_ARGS;
2172 for (i = 0; i < tcp->u_nargs; i++)
2173 tcp->u_arg[i] = regs.uregs[i];
2174# elif defined(AVR32)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002175 tcp->u_nargs = sysent[tcp->scno].nargs;
2176 tcp->u_arg[0] = regs.r12;
2177 tcp->u_arg[1] = regs.r11;
2178 tcp->u_arg[2] = regs.r10;
2179 tcp->u_arg[3] = regs.r9;
2180 tcp->u_arg[4] = regs.r5;
2181 tcp->u_arg[5] = regs.r3;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002182# elif defined(BFIN)
2183 int i;
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02002184 static const int argreg[] = { PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5 };
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00002185
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002186 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002187 tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002188 else
2189 tcp->u_nargs = ARRAY_SIZE(argreg);
2190
2191 for (i = 0; i < tcp->u_nargs; ++i)
2192 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
2193 return -1;
2194# elif defined(SH)
2195 int i;
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02002196 static const int syscall_regs[] = {
2197 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6), 4 * (REG_REG0+7),
2198 4 * (REG_REG0 ), 4 * (REG_REG0+1), 4 * (REG_REG0+2)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002199 };
2200
2201 tcp->u_nargs = sysent[tcp->scno].nargs;
2202 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02002203 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002204 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002205 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002206# elif defined(SH64)
2207 int i;
2208 /* Registers used by SH5 Linux system calls for parameters */
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02002209 static const int syscall_regs[] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00002210
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002211 /*
2212 * TODO: should also check that the number of arguments encoded
2213 * in the trap number matches the number strace expects.
2214 */
2215 /*
2216 assert(sysent[tcp->scno].nargs < ARRAY_SIZE(syscall_regs));
2217 */
Roland McGrathe1e584b2003-06-02 19:18:58 +00002218
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002219 tcp->u_nargs = sysent[tcp->scno].nargs;
2220 for (i = 0; i < tcp->u_nargs; i++) {
2221 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
2222 return -1;
2223 }
2224# elif defined(X86_64)
2225 int i;
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02002226 static const int argreg[SUPPORTED_PERSONALITIES][MAX_ARGS] = {
2227 { 8 * RDI, 8 * RSI, 8 * RDX, 8 * R10, 8 * R8 , 8 * R9 }, /* x86-64 ABI */
2228 { 8 * RBX, 8 * RCX, 8 * RDX, 8 * RSI, 8 * RDI, 8 * RBP } /* i386 ABI */
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002229 };
2230
2231 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Roland McGrathe1e584b2003-06-02 19:18:58 +00002232 tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002233 else
2234 tcp->u_nargs = MAX_ARGS;
2235 for (i = 0; i < tcp->u_nargs; i++) {
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02002236 if (upeek(tcp, argreg[current_personality][i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002237 return -1;
Roland McGrathe1e584b2003-06-02 19:18:58 +00002238 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002239# elif defined(MICROBLAZE)
2240 int i;
2241 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
2242 tcp->u_nargs = sysent[tcp->scno].nargs;
2243 else
2244 tcp->u_nargs = 0;
2245 for (i = 0; i < tcp->u_nargs; i++) {
2246 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
2247 return -1;
2248 }
2249# elif defined(CRISV10) || defined(CRISV32)
2250 int i;
2251 static const int crisregs[] = {
2252 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02002253 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002254 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00002255
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002256 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
2257 tcp->u_nargs = sysent[tcp->scno].nargs;
2258 else
2259 tcp->u_nargs = 0;
2260 for (i = 0; i < tcp->u_nargs; i++) {
2261 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
2262 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00002263 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002264# elif defined(TILE)
2265 int i;
2266 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2267 tcp->u_nargs = sysent[tcp->scno].nargs;
2268 else
2269 tcp->u_nargs = MAX_ARGS;
2270 for (i = 0; i < tcp->u_nargs; ++i) {
2271 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
2272 return -1;
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02002273 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002274# elif defined(M68K)
2275 int i;
2276 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2277 tcp->u_nargs = sysent[tcp->scno].nargs;
2278 else
2279 tcp->u_nargs = MAX_ARGS;
2280 for (i = 0; i < tcp->u_nargs; i++) {
2281 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
2282 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002283 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002284# else /* Other architecture (like i386) (32bits specific) */
2285 int i;
2286 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2287 tcp->u_nargs = sysent[tcp->scno].nargs;
2288 else
2289 tcp->u_nargs = MAX_ARGS;
2290 for (i = 0; i < tcp->u_nargs; i++) {
2291 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
2292 return -1;
Chris Metcalfc8c66982009-12-28 10:00:15 -05002293 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002294# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002295#endif /* LINUX */
2296#ifdef SUNOS4
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002297 int i;
2298 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2299 tcp->u_nargs = sysent[tcp->scno].nargs;
2300 else
2301 tcp->u_nargs = MAX_ARGS;
2302 for (i = 0; i < tcp->u_nargs; i++) {
2303 struct user *u;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002304
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002305 if (upeek(tcp, uoff(u_arg[0]) +
2306 (i * sizeof(u->u_arg[0])), &tcp->u_arg[i]) < 0)
2307 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002308 }
2309#endif /* SUNOS4 */
2310#ifdef SVR4
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002311# ifdef MIPS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002312 /*
2313 * SGI is broken: even though it has pr_sysarg, it doesn't
2314 * set them on system call entry. Get a clue.
2315 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002316 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002317 tcp->u_nargs = sysent[tcp->scno].nargs;
2318 else
2319 tcp->u_nargs = tcp->status.pr_nsysarg;
2320 if (tcp->u_nargs > 4) {
2321 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002322 4 * sizeof(tcp->u_arg[0]));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002323 umoven(tcp, tcp->status.pr_reg[CTX_SP] + 16,
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002324 (tcp->u_nargs - 4) * sizeof(tcp->u_arg[0]), (char *) (tcp->u_arg + 4));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002325 }
2326 else {
2327 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002328 tcp->u_nargs * sizeof(tcp->u_arg[0]));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002329 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002330# elif UNIXWARE >= 2
John Hughes25299712001-03-06 10:10:06 +00002331 /*
2332 * Like SGI, UnixWare doesn't set pr_sysarg until system call exit
2333 */
2334 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2335 tcp->u_nargs = sysent[tcp->scno].nargs;
2336 else
2337 tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;
2338 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002339 tcp->u_nargs * sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2340# elif defined(HAVE_PR_SYSCALL)
2341 int i;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002342 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002343 tcp->u_nargs = sysent[tcp->scno].nargs;
2344 else
2345 tcp->u_nargs = tcp->status.pr_nsysarg;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002346 for (i = 0; i < tcp->u_nargs; i++)
2347 tcp->u_arg[i] = tcp->status.pr_sysarg[i];
2348# elif defined(I386)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002349 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002350 tcp->u_nargs = sysent[tcp->scno].nargs;
2351 else
2352 tcp->u_nargs = 5;
Denys Vlasenko4660fe62011-06-09 01:32:23 +02002353 if (tcp->u_nargs > 0)
2354 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002355 tcp->u_nargs * sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2356# else
John Hughes25299712001-03-06 10:10:06 +00002357 I DONT KNOW WHAT TO DO
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002358# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002359#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002360#ifdef FREEBSD
2361 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2362 sysent[tcp->scno].nargs > tcp->status.val)
2363 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002364 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002365 tcp->u_nargs = tcp->status.val;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002366 if (tcp->u_nargs < 0)
2367 tcp->u_nargs = 0;
2368 if (tcp->u_nargs > MAX_ARGS)
2369 tcp->u_nargs = MAX_ARGS;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002370 switch (regs.r_eax) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002371 case SYS___syscall:
2372 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2373 regs.r_esp + sizeof(int) + sizeof(quad_t));
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002374 break;
2375 case SYS_syscall:
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002376 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2377 regs.r_esp + 2 * sizeof(int));
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002378 break;
2379 default:
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002380 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2381 regs.r_esp + sizeof(int));
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002382 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002383 }
2384#endif /* FREEBSD */
Pavel Machek4dc3b142000-02-01 17:58:41 +00002385 return 1;
2386}
2387
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002388static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002389trace_syscall_entering(struct tcb *tcp)
2390{
2391 int res, scno_good;
2392
2393 scno_good = res = get_scno(tcp);
2394 if (res == 0)
2395 return res;
2396 if (res == 1)
2397 res = syscall_fixup(tcp);
2398 if (res == 0)
2399 return res;
2400 if (res == 1)
2401 res = syscall_enter(tcp);
2402 if (res == 0)
2403 return res;
2404
2405 if (res != 1) {
2406 printleader(tcp);
2407 tcp->flags &= ~TCB_REPRINT;
2408 tcp_last = tcp;
2409 if (scno_good != 1)
2410 tprintf("????" /* anti-trigraph gap */ "(");
2411 else if (tcp->scno >= nsyscalls || tcp->scno < 0)
2412 tprintf("syscall_%lu(", tcp->scno);
2413 else
2414 tprintf("%s(", sysent[tcp->scno].sys_name);
2415 /*
2416 * " <unavailable>" will be added later by the code which
2417 * detects ptrace errors.
2418 */
2419 goto ret;
2420 }
2421
2422 switch (known_scno(tcp)) {
2423#ifdef SYS_socket_subcall
2424 case SYS_socketcall:
2425 decode_subcall(tcp, SYS_socket_subcall,
2426 SYS_socket_nsubcalls, deref_style);
2427 break;
2428#endif
2429#ifdef SYS_ipc_subcall
2430 case SYS_ipc:
2431 decode_subcall(tcp, SYS_ipc_subcall,
2432 SYS_ipc_nsubcalls, shift_style);
2433 break;
2434#endif
2435#ifdef SVR4
2436#ifdef SYS_pgrpsys_subcall
2437 case SYS_pgrpsys:
2438 decode_subcall(tcp, SYS_pgrpsys_subcall,
2439 SYS_pgrpsys_nsubcalls, shift_style);
2440 break;
2441#endif /* SYS_pgrpsys_subcall */
2442#ifdef SYS_sigcall_subcall
2443 case SYS_sigcall:
2444 decode_subcall(tcp, SYS_sigcall_subcall,
2445 SYS_sigcall_nsubcalls, mask_style);
2446 break;
2447#endif /* SYS_sigcall_subcall */
2448 case SYS_msgsys:
2449 decode_subcall(tcp, SYS_msgsys_subcall,
2450 SYS_msgsys_nsubcalls, shift_style);
2451 break;
2452 case SYS_shmsys:
2453 decode_subcall(tcp, SYS_shmsys_subcall,
2454 SYS_shmsys_nsubcalls, shift_style);
2455 break;
2456 case SYS_semsys:
2457 decode_subcall(tcp, SYS_semsys_subcall,
2458 SYS_semsys_nsubcalls, shift_style);
2459 break;
2460 case SYS_sysfs:
2461 decode_subcall(tcp, SYS_sysfs_subcall,
2462 SYS_sysfs_nsubcalls, shift_style);
2463 break;
2464 case SYS_spcall:
2465 decode_subcall(tcp, SYS_spcall_subcall,
2466 SYS_spcall_nsubcalls, shift_style);
2467 break;
2468#ifdef SYS_context_subcall
2469 case SYS_context:
2470 decode_subcall(tcp, SYS_context_subcall,
2471 SYS_context_nsubcalls, shift_style);
2472 break;
2473#endif /* SYS_context_subcall */
2474#ifdef SYS_door_subcall
2475 case SYS_door:
2476 decode_subcall(tcp, SYS_door_subcall,
2477 SYS_door_nsubcalls, door_style);
2478 break;
2479#endif /* SYS_door_subcall */
2480#ifdef SYS_kaio_subcall
2481 case SYS_kaio:
2482 decode_subcall(tcp, SYS_kaio_subcall,
2483 SYS_kaio_nsubcalls, shift_style);
2484 break;
2485#endif
2486#endif /* SVR4 */
2487#ifdef FREEBSD
2488 case SYS_msgsys:
2489 case SYS_shmsys:
2490 case SYS_semsys:
2491 decode_subcall(tcp, 0, 0, table_style);
2492 break;
2493#endif
2494#ifdef SUNOS4
2495 case SYS_semsys:
2496 decode_subcall(tcp, SYS_semsys_subcall,
2497 SYS_semsys_nsubcalls, shift_style);
2498 break;
2499 case SYS_msgsys:
2500 decode_subcall(tcp, SYS_msgsys_subcall,
2501 SYS_msgsys_nsubcalls, shift_style);
2502 break;
2503 case SYS_shmsys:
2504 decode_subcall(tcp, SYS_shmsys_subcall,
2505 SYS_shmsys_nsubcalls, shift_style);
2506 break;
2507#endif
2508 }
2509
2510 internal_syscall(tcp);
2511
2512 if ((tcp->scno >= 0 && tcp->scno < nsyscalls &&
2513 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
2514 (tracing_paths && !pathtrace_match(tcp))) {
2515 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
2516 return 0;
2517 }
2518
2519 tcp->flags &= ~TCB_FILTERED;
2520
2521 if (cflag == CFLAG_ONLY_STATS) {
2522 res = 0;
2523 goto ret;
2524 }
2525
2526 printleader(tcp);
2527 tcp->flags &= ~TCB_REPRINT;
2528 tcp_last = tcp;
2529 if (tcp->scno >= nsyscalls || tcp->scno < 0)
2530 tprintf("syscall_%lu(", tcp->scno);
2531 else
2532 tprintf("%s(", sysent[tcp->scno].sys_name);
2533 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2534 ((qual_flags[tcp->scno] & QUAL_RAW) &&
2535 sysent[tcp->scno].sys_func != sys_exit))
2536 res = printargs(tcp);
2537 else
2538 res = (*sysent[tcp->scno].sys_func)(tcp);
2539
2540 if (fflush(tcp->outf) == EOF)
2541 return -1;
2542 ret:
2543 tcp->flags |= TCB_INSYSCALL;
2544 /* Measure the entrance time as late as possible to avoid errors. */
2545 if (dtime || cflag)
2546 gettimeofday(&tcp->etime, NULL);
2547 return res;
2548}
2549
2550static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002551trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002552{
2553 int sys_res;
2554 struct timeval tv;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002555 int res, scno_good;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002556 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002557
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002558 /* Measure the exit time as early as possible to avoid errors. */
2559 if (dtime || cflag)
2560 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002561
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002562 /* BTW, why we don't just memorize syscall no. on entry
2563 * in tcp->something?
2564 */
2565 scno_good = res = get_scno(tcp);
2566 if (res == 0)
2567 return res;
2568 if (res == 1)
2569 res = syscall_fixup(tcp);
2570 if (res == 0)
2571 return res;
2572 if (res == 1)
2573 res = get_error(tcp);
2574 if (res == 0)
2575 return res;
2576 if (res == 1)
2577 internal_syscall(tcp);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002578
Grant Edwards8a082772011-04-07 20:25:40 +00002579 if (res == 1 && filtered(tcp)) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002580 goto ret;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002581 }
2582
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002583 if (tcp->flags & TCB_REPRINT) {
2584 printleader(tcp);
2585 tprintf("<... ");
2586 if (scno_good != 1)
2587 tprintf("????");
2588 else if (tcp->scno >= nsyscalls || tcp->scno < 0)
2589 tprintf("syscall_%lu", tcp->scno);
2590 else
2591 tprintf("%s", sysent[tcp->scno].sys_name);
2592 tprintf(" resumed> ");
2593 }
2594
2595 if (cflag) {
2596 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002597 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002598 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002599 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002600 }
2601 }
2602
2603 if (res != 1) {
2604 tprintf(") ");
2605 tabto(acolumn);
2606 tprintf("= ? <unavailable>");
2607 printtrailer();
2608 tcp->flags &= ~TCB_INSYSCALL;
2609 return res;
2610 }
2611
2612 if (tcp->scno >= nsyscalls || tcp->scno < 0
2613 || (qual_flags[tcp->scno] & QUAL_RAW))
2614 sys_res = printargs(tcp);
2615 else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002616 /* FIXME: not_failing_only (IOW, option -z) is broken:
2617 * failure of syscall is known only after syscall return.
2618 * Thus we end up with something like this on, say, ENOENT:
2619 * open("doesnt_exist", O_RDONLY <unfinished ...>
2620 * {next syscall decode}
2621 * whereas the intended result is that open(...) line
2622 * is not shown at all.
2623 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002624 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002625 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002626 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2627 }
2628
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002629 tprintf(") ");
2630 tabto(acolumn);
Denys Vlasenko3b738812011-08-22 02:06:35 +02002631 u_error = tcp->u_error;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002632 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2633 qual_flags[tcp->scno] & QUAL_RAW) {
2634 if (u_error)
2635 tprintf("= -1 (errno %ld)", u_error);
2636 else
2637 tprintf("= %#lx", tcp->u_rval);
2638 }
2639 else if (!(sys_res & RVAL_NONE) && u_error) {
2640 switch (u_error) {
2641#ifdef LINUX
2642 case ERESTARTSYS:
2643 tprintf("= ? ERESTARTSYS (To be restarted)");
2644 break;
2645 case ERESTARTNOINTR:
2646 tprintf("= ? ERESTARTNOINTR (To be restarted)");
2647 break;
2648 case ERESTARTNOHAND:
2649 tprintf("= ? ERESTARTNOHAND (To be restarted)");
2650 break;
2651 case ERESTART_RESTARTBLOCK:
2652 tprintf("= ? ERESTART_RESTARTBLOCK (To be restarted)");
2653 break;
2654#endif /* LINUX */
2655 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002656 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002657 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002658 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002659 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002660 strerror(u_error));
2661 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002662 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002663 strerror(u_error));
2664 break;
2665 }
2666 if ((sys_res & RVAL_STR) && tcp->auxstr)
2667 tprintf(" (%s)", tcp->auxstr);
2668 }
2669 else {
2670 if (sys_res & RVAL_NONE)
2671 tprintf("= ?");
2672 else {
2673 switch (sys_res & RVAL_MASK) {
2674 case RVAL_HEX:
2675 tprintf("= %#lx", tcp->u_rval);
2676 break;
2677 case RVAL_OCTAL:
2678 tprintf("= %#lo", tcp->u_rval);
2679 break;
2680 case RVAL_UDECIMAL:
2681 tprintf("= %lu", tcp->u_rval);
2682 break;
2683 case RVAL_DECIMAL:
2684 tprintf("= %ld", tcp->u_rval);
2685 break;
2686#ifdef HAVE_LONG_LONG
2687 case RVAL_LHEX:
2688 tprintf("= %#llx", tcp->u_lrval);
2689 break;
2690 case RVAL_LOCTAL:
2691 tprintf("= %#llo", tcp->u_lrval);
2692 break;
2693 case RVAL_LUDECIMAL:
2694 tprintf("= %llu", tcp->u_lrval);
2695 break;
2696 case RVAL_LDECIMAL:
2697 tprintf("= %lld", tcp->u_lrval);
2698 break;
2699#endif
2700 default:
2701 fprintf(stderr,
2702 "invalid rval format\n");
2703 break;
2704 }
2705 }
2706 if ((sys_res & RVAL_STR) && tcp->auxstr)
2707 tprintf(" (%s)", tcp->auxstr);
2708 }
2709 if (dtime) {
2710 tv_sub(&tv, &tv, &tcp->etime);
2711 tprintf(" <%ld.%06ld>",
2712 (long) tv.tv_sec, (long) tv.tv_usec);
2713 }
2714 printtrailer();
2715
2716 dumpio(tcp);
2717 if (fflush(tcp->outf) == EOF)
2718 return -1;
Denys Vlasenko3b738812011-08-22 02:06:35 +02002719 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002720 tcp->flags &= ~TCB_INSYSCALL;
2721 return 0;
2722}
2723
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002724int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002725trace_syscall(struct tcb *tcp)
2726{
2727 return exiting(tcp) ?
2728 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2729}
2730
2731int
Denys Vlasenko12014262011-05-30 14:00:14 +02002732printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002733{
2734 if (entering(tcp)) {
2735 int i;
2736
2737 for (i = 0; i < tcp->u_nargs; i++)
2738 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
2739 }
2740 return 0;
2741}
2742
2743long
Denys Vlasenko12014262011-05-30 14:00:14 +02002744getrval2(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002745{
2746 long val = -1;
2747
2748#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002749#if defined (SPARC) || defined (SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04002750 struct pt_regs regs;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002751 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002752 return -1;
Mike Frysinger8566c502009-10-12 11:05:14 -04002753 val = regs.u_regs[U_REG_O1];
Roland McGrath6b1d43e2003-03-31 01:05:01 +00002754#elif defined(SH)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002755 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
Roland McGrath6b1d43e2003-03-31 01:05:01 +00002756 return -1;
Roland McGrathb4ce1762004-03-01 20:30:48 +00002757#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002758 if (upeek(tcp, PT_R9, &val) < 0)
Roland McGrathb4ce1762004-03-01 20:30:48 +00002759 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002760#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002761#endif /* LINUX */
2762
2763#ifdef SUNOS4
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002764 if (upeek(tcp, uoff(u_rval2), &val) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002765 return -1;
2766#endif /* SUNOS4 */
2767
2768#ifdef SVR4
2769#ifdef SPARC
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002770 val = tcp->status.PR_REG[R_O1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002771#endif /* SPARC */
2772#ifdef I386
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002773 val = tcp->status.PR_REG[EDX];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002774#endif /* I386 */
Michal Ludvig0e035502002-09-23 15:41:01 +00002775#ifdef X86_64
2776 val = tcp->status.PR_REG[RDX];
2777#endif /* X86_64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002778#ifdef MIPS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002779 val = tcp->status.PR_REG[CTX_V1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002780#endif /* MIPS */
2781#endif /* SVR4 */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002782
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002783#ifdef FREEBSD
2784 struct reg regs;
2785 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
2786 val = regs.r_edx;
Roland McGrath761b5d72002-12-15 23:58:31 +00002787#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002788 return val;
2789}
2790
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +00002791#ifdef SUNOS4
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002792/*
2793 * Apparently, indirect system calls have already be converted by ptrace(2),
2794 * so if you see "indir" this program has gone astray.
2795 */
2796int
Denys Vlasenko12014262011-05-30 14:00:14 +02002797sys_indir(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002798{
2799 int i, scno, nargs;
2800
2801 if (entering(tcp)) {
Denys Vlasenko5d645812011-08-20 12:48:18 +02002802 scno = tcp->u_arg[0];
2803 if (scno > nsyscalls) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002804 fprintf(stderr, "Bogus syscall: %u\n", scno);
2805 return 0;
2806 }
2807 nargs = sysent[scno].nargs;
2808 tprintf("%s", sysent[scno].sys_name);
2809 for (i = 0; i < nargs; i++)
2810 tprintf(", %#lx", tcp->u_arg[i+1]);
2811 }
2812 return 0;
2813}
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +00002814#endif /* SUNOS4 */
Dmitry V. Levin2e55ff42008-09-03 01:02:46 +00002815
2816int
2817is_restart_error(struct tcb *tcp)
2818{
2819#ifdef LINUX
2820 if (!syserror(tcp))
2821 return 0;
2822 switch (tcp->u_error) {
2823 case ERESTARTSYS:
2824 case ERESTARTNOINTR:
2825 case ERESTARTNOHAND:
2826 case ERESTART_RESTARTBLOCK:
2827 return 1;
2828 default:
2829 break;
2830 }
2831#endif /* LINUX */
2832 return 0;
2833}