blob: 2af908573a8b541c11cc1b4b214c2203570fc361 [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;
Denys Vlasenkoafc64032011-08-23 13:29:01 +0200207unsigned nsyscalls;
208unsigned nerrnos;
209unsigned nsignals;
210unsigned nioctlents;
Denys Vlasenko39fca622011-08-20 02:12:33 +0200211int *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;
Denys Vlasenko4b887a52011-08-23 13:32:38 +0200573 int i, n;
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];
Denys Vlasenko4b887a52011-08-23 13:32:38 +0200581 tcp->u_nargs = n = sysent[tcp->scno].nargs;
582 for (i = 0; i < n; i++)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000583 tcp->u_arg[i] = tcp->u_arg[i + 1];
584 break;
585 case deref_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000586 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
587 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000588 tcp->scno = subcall + tcp->u_arg[0];
589 addr = tcp->u_arg[1];
Denys Vlasenko4b887a52011-08-23 13:32:38 +0200590 tcp->u_nargs = n = sysent[tcp->scno].nargs;
591 for (i = 0; i < n; i++) {
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000592 if (size == sizeof(int)) {
593 unsigned int arg;
594 if (umove(tcp, addr, &arg) < 0)
595 arg = 0;
596 tcp->u_arg[i] = arg;
597 }
598 else if (size == sizeof(long)) {
599 unsigned long arg;
600 if (umove(tcp, addr, &arg) < 0)
601 arg = 0;
602 tcp->u_arg[i] = arg;
603 }
604 else
605 abort();
606 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000607 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000608 break;
609 case mask_style:
610 mask = (tcp->u_arg[0] >> 8) & 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000611 for (i = 0; mask; i++)
612 mask >>= 1;
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000613 if (i >= nsubcalls)
614 return;
615 tcp->u_arg[0] &= 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000616 tcp->scno = subcall + i;
Denys Vlasenkoafc64032011-08-23 13:29:01 +0200617 tcp->u_nargs = sysent[tcp->scno].nargs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000618 break;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000619 case door_style:
620 /*
621 * Oh, yuck. The call code is the *sixth* argument.
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000622 * (don't you mean the *last* argument? - JH)
Wichert Akkerman8829a551999-06-11 13:18:40 +0000623 */
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000624 if (tcp->u_arg[5] < 0 || tcp->u_arg[5] >= nsubcalls)
625 return;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000626 tcp->scno = subcall + tcp->u_arg[5];
Denys Vlasenkoafc64032011-08-23 13:29:01 +0200627 tcp->u_nargs = sysent[tcp->scno].nargs;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000628 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000629#ifdef FREEBSD
630 case table_style:
Dmitry V. Levinfcda7a52011-06-13 21:58:43 +0000631 for (i = 0; i < ARRAY_SIZE(subcalls_table); i++)
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000632 if (subcalls_table[i].call == tcp->scno) break;
Dmitry V. Levinfcda7a52011-06-13 21:58:43 +0000633 if (i < ARRAY_SIZE(subcalls_table) &&
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000634 tcp->u_arg[0] >= 0 && tcp->u_arg[0] < subcalls_table[i].nsubcalls) {
635 tcp->scno = subcalls_table[i].subcalls[tcp->u_arg[0]];
636 for (i = 0; i < tcp->u_nargs; i++)
637 tcp->u_arg[i] = tcp->u_arg[i + 1];
638 }
639 break;
640#endif /* FREEBSD */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000641 }
642}
643#endif
644
645struct tcb *tcp_last = NULL;
646
647static int
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000648internal_syscall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000649{
650 /*
651 * We must always trace a few critical system calls in order to
652 * correctly support following forks in the presence of tracing
653 * qualifiers.
654 */
Denys Vlasenkoa7949742011-08-21 17:26:55 +0200655 int (*func)();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000656
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000657 if (tcp->scno < 0 || tcp->scno >= nsyscalls)
658 return 0;
659
660 func = sysent[tcp->scno].sys_func;
661
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000662 if ( sys_fork == func
663#if defined(FREEBSD) || defined(LINUX) || defined(SUNOS4)
664 || sys_vfork == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000665#endif
Dmitry V. Levin257e1572009-12-26 17:55:24 +0000666#ifdef LINUX
667 || sys_clone == func
668#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000669#if UNIXWARE > 2
670 || sys_rfork == func
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000671#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000672 )
673 return internal_fork(tcp);
674
Denys Vlasenkoa7949742011-08-21 17:26:55 +0200675#if defined SUNOS4 || (defined LINUX && defined TCB_WAITEXECVE)
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000676 if ( sys_execve == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +0200677# if defined(SPARC) || defined(SPARC64) || defined(SUNOS4)
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000678 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +0200679# endif
680# if UNIXWARE > 2
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000681 || sys_rexecve == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +0200682# endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000683 )
684 return internal_exec(tcp);
Denys Vlasenkoa7949742011-08-21 17:26:55 +0200685#endif
Dmitry V. Levinb2f86992006-12-21 11:44:28 +0000686
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000687 return 0;
688}
689
Wichert Akkermanc7926982000-04-10 22:22:31 +0000690
691#ifdef LINUX
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200692# if defined (I386)
693static long eax;
694# elif defined (IA64)
695long r8, r10, psr; /* TODO: make static? */
696long ia32 = 0; /* not static */
697# elif defined (POWERPC)
698static long result, flags;
699# elif defined (M68K)
700static long d0;
701# elif defined(BFIN)
702static long r0;
703# elif defined (ARM)
704static struct pt_regs regs;
705# elif defined (ALPHA)
706static long r0;
707static long a3;
708# elif defined(AVR32)
709static struct pt_regs regs;
710# elif defined (SPARC) || defined (SPARC64)
711static struct pt_regs regs;
712static unsigned long trap;
713# elif defined(LINUX_MIPSN32)
714static long long a3;
715static long long r2;
716# elif defined(MIPS)
717static long a3;
718static long r2;
719# elif defined(S390) || defined(S390X)
720static long gpr2;
721static long pc;
722static long syscall_mode;
723# elif defined(HPPA)
724static long r28;
725# elif defined(SH)
726static long r0;
727# elif defined(SH64)
728static long r9;
729# elif defined(X86_64)
730static long rax;
731# elif defined(CRISV10) || defined(CRISV32)
732static long r10;
733# elif defined(MICROBLAZE)
734static long r3;
735# endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000736#endif /* LINUX */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000737#ifdef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200738struct reg regs; /* TODO: make static? */
Roland McGrath761b5d72002-12-15 23:58:31 +0000739#endif /* FREEBSD */
Wichert Akkermanc7926982000-04-10 22:22:31 +0000740
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200741/* Returns:
742 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
743 * 1: ok, continue in trace_syscall().
744 * other: error, trace_syscall() should print error indicator
745 * ("????" etc) and bail out.
746 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000747int
Denys Vlasenkofb036672009-01-23 16:30:26 +0000748get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000749{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000750 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000751
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000752#ifdef LINUX
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000753# if defined(S390) || defined(S390X)
Roland McGrath96dc5142003-01-20 10:23:04 +0000754 if (tcp->flags & TCB_WAITEXECVE) {
755 /*
756 * When the execve system call completes successfully, the
757 * new process still has -ENOSYS (old style) or __NR_execve
758 * (new style) in gpr2. We cannot recover the scno again
759 * by disassembly, because the image that executed the
760 * syscall is gone now. Fortunately, we don't want it. We
761 * leave the flag set so that syscall_fixup can fake the
762 * result.
763 */
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200764 if (exiting(tcp))
Roland McGrath96dc5142003-01-20 10:23:04 +0000765 return 1;
766 /*
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200767 * This is the post-execve SIGTRAP. We cannot try to read
Roland McGrath96dc5142003-01-20 10:23:04 +0000768 * the system call here either.
769 */
770 tcp->flags &= ~TCB_WAITEXECVE;
771 return 0;
772 }
Roland McGrath2f924ca2003-06-26 22:23:28 +0000773
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000774 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200775 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000776
777 if (syscall_mode != -ENOSYS) {
778 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000779 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000780 */
781 scno = syscall_mode;
782 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000783 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000784 * Old style of "passing" the scno via the SVC instruction.
785 */
786
787 long opcode, offset_reg, tmp;
788 void * svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200789 static const int gpr_offset[16] = {
790 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
791 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
792 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
793 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
794 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000795
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000796 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000797 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000798 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000799 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000800 if (errno) {
801 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000802 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000803 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000804
805 /*
806 * We have to check if the SVC got executed directly or via an
807 * EXECUTE instruction. In case of EXECUTE it is necessary to do
808 * instruction decoding to derive the system call number.
809 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
810 * so that this doesn't work if a SVC opcode is part of an EXECUTE
811 * opcode. Since there is no way to find out the opcode size this
812 * is the best we can do...
813 */
814
815 if ((opcode & 0xff00) == 0x0a00) {
816 /* SVC opcode */
817 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000818 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000819 else {
820 /* SVC got executed by EXECUTE instruction */
821
822 /*
823 * Do instruction decoding of EXECUTE. If you really want to
824 * understand this, read the Principles of Operations.
825 */
826 svc_addr = (void *) (opcode & 0xfff);
827
828 tmp = 0;
829 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000830 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000831 return -1;
832 svc_addr += tmp;
833
834 tmp = 0;
835 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000836 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000837 return -1;
838 svc_addr += tmp;
839
Denys Vlasenkofb036672009-01-23 16:30:26 +0000840 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000841 if (errno)
842 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000843# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000844 scno >>= 48;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000845# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000846 scno >>= 16;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000847# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000848 tmp = 0;
849 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000850 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000851 return -1;
852
853 scno = (scno | tmp) & 0xff;
854 }
855 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000856# elif defined (POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000857 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000858 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200859 if (entering(tcp)) {
860 /* Check if this is the post-execve SIGTRAP. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000861 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
862 tcp->flags &= ~TCB_WAITEXECVE;
863 return 0;
864 }
865 }
Andreas Schwabd69fa492010-07-12 21:39:57 +0200866
867# ifdef POWERPC64
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200868 if (entering(tcp)) {
Denys Vlasenkodeec74e2011-08-20 00:03:10 +0200869 /* TODO: speed up strace by not doing this at every syscall.
870 * We only need to do it after execve.
871 */
872 int currpers;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200873 long val;
874 int pid = tcp->pid;
875
876 /* Check for 64/32 bit mode. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200877 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
Andreas Schwabd69fa492010-07-12 21:39:57 +0200878 return -1;
879 /* SF is bit 0 of MSR */
880 if (val < 0)
881 currpers = 0;
882 else
883 currpers = 1;
884 if (currpers != current_personality) {
885 static const char *const names[] = {"64 bit", "32 bit"};
886 set_personality(currpers);
Dmitry V. Levinbdafa1a2010-12-02 23:38:13 +0000887 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
Andreas Schwabd69fa492010-07-12 21:39:57 +0200888 pid, names[current_personality]);
889 }
890 }
891# endif
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000892# elif defined(AVR32)
893 /*
894 * Read complete register set in one go.
895 */
896 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
897 return -1;
898
899 /*
900 * We only need to grab the syscall number on syscall entry.
901 */
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200902 if (entering(tcp)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000903 scno = regs.r8;
904
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200905 /* Check if this is the post-execve SIGTRAP. */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000906 if (tcp->flags & TCB_WAITEXECVE) {
907 tcp->flags &= ~TCB_WAITEXECVE;
908 return 0;
909 }
910 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000911# elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000912 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000913 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000914# elif defined (I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000915 if (upeek(tcp, 4*ORIG_EAX, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000916 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000917# elif defined (X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000918 if (upeek(tcp, 8*ORIG_RAX, &scno) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +0000919 return -1;
920
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200921 if (entering(tcp)) {
Denys Vlasenkodeec74e2011-08-20 00:03:10 +0200922 /* TODO: speed up strace by not doing this at every syscall.
923 * We only need to do it after execve.
924 */
925 int currpers;
Michal Ludvig0e035502002-09-23 15:41:01 +0000926 long val;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000927 int pid = tcp->pid;
Michal Ludvig0e035502002-09-23 15:41:01 +0000928
929 /* Check CS register value. On x86-64 linux it is:
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200930 * 0x33 for long mode (64 bit)
931 * 0x23 for compatibility mode (32 bit)
Roland McGrath761b5d72002-12-15 23:58:31 +0000932 * It takes only one ptrace and thus doesn't need
Michal Ludvig0e035502002-09-23 15:41:01 +0000933 * to be cached.
934 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000935 if (upeek(tcp, 8*CS, &val) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +0000936 return -1;
Denys Vlasenko8236f252009-01-02 18:10:08 +0000937 switch (val) {
Michal Ludvig0e035502002-09-23 15:41:01 +0000938 case 0x23: currpers = 1; break;
939 case 0x33: currpers = 0; break;
940 default:
941 fprintf(stderr, "Unknown value CS=0x%02X while "
942 "detecting personality of process "
943 "PID=%d\n", (int)val, pid);
944 currpers = current_personality;
945 break;
946 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000947# if 0
Michal Ludvig0e035502002-09-23 15:41:01 +0000948 /* This version analyzes the opcode of a syscall instruction.
949 * (int 0x80 on i386 vs. syscall on x86-64)
950 * It works, but is too complicated.
951 */
952 unsigned long val, rip, i;
953
Denys Vlasenko8236f252009-01-02 18:10:08 +0000954 if (upeek(tcp, 8*RIP, &rip) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +0000955 perror("upeek(RIP)");
Roland McGrath761b5d72002-12-15 23:58:31 +0000956
Michal Ludvig0e035502002-09-23 15:41:01 +0000957 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
Denys Vlasenko8236f252009-01-02 18:10:08 +0000958 rip -= 2;
Michal Ludvig0e035502002-09-23 15:41:01 +0000959 errno = 0;
960
Denys Vlasenko8236f252009-01-02 18:10:08 +0000961 call = ptrace(PTRACE_PEEKTEXT, pid, (char *)rip, (char *)0);
Roland McGrath761b5d72002-12-15 23:58:31 +0000962 if (errno)
Dmitry V. Levinbdafa1a2010-12-02 23:38:13 +0000963 fprintf(stderr, "ptrace_peektext failed: %s\n",
Michal Ludvig0e035502002-09-23 15:41:01 +0000964 strerror(errno));
Denys Vlasenko8236f252009-01-02 18:10:08 +0000965 switch (call & 0xffff) {
Michal Ludvig0e035502002-09-23 15:41:01 +0000966 /* x86-64: syscall = 0x0f 0x05 */
967 case 0x050f: currpers = 0; break;
968 /* i386: int 0x80 = 0xcd 0x80 */
969 case 0x80cd: currpers = 1; break;
970 default:
971 currpers = current_personality;
Roland McGrath761b5d72002-12-15 23:58:31 +0000972 fprintf(stderr,
Michal Ludvig0e035502002-09-23 15:41:01 +0000973 "Unknown syscall opcode (0x%04X) while "
974 "detecting personality of process "
975 "PID=%d\n", (int)call, pid);
976 break;
977 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000978# endif
Denys Vlasenko8236f252009-01-02 18:10:08 +0000979 if (currpers != current_personality) {
980 static const char *const names[] = {"64 bit", "32 bit"};
Michal Ludvig0e035502002-09-23 15:41:01 +0000981 set_personality(currpers);
Dmitry V. Levinbdafa1a2010-12-02 23:38:13 +0000982 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
Michal Ludvig0e035502002-09-23 15:41:01 +0000983 pid, names[current_personality]);
984 }
Roland McGrath761b5d72002-12-15 23:58:31 +0000985 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000986# elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000987# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200988 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000989 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200990 if (entering(tcp)) {
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000991 if (ia32) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000992 if (upeek(tcp, PT_R1, &scno) < 0) /* orig eax */
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000993 return -1;
994 } else {
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200995 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000996 return -1;
997 }
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200998 /* Check if this is the post-execve SIGTRAP. */
Roland McGrathba954762003-03-05 06:29:06 +0000999 if (tcp->flags & TCB_WAITEXECVE) {
1000 tcp->flags &= ~TCB_WAITEXECVE;
1001 return 0;
1002 }
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001003 } else {
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001004 /* Syscall exit */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001005 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001006 return -1;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001007 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001008 return -1;
1009 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001010# elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001011 /*
1012 * Read complete register set in one go.
1013 */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001014 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +00001015 return -1;
1016
1017 /*
1018 * We only need to grab the syscall number on syscall entry.
1019 */
1020 if (regs.ARM_ip == 0) {
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001021 if (entering(tcp)) {
1022 /* Check if this is the post-execve SIGTRAP. */
Roland McGrath9bc63402007-11-01 21:42:18 +00001023 if (tcp->flags & TCB_WAITEXECVE) {
1024 tcp->flags &= ~TCB_WAITEXECVE;
1025 return 0;
1026 }
1027 }
1028
Roland McGrath0f87c492003-06-03 23:29:04 +00001029 /*
1030 * Note: we only deal with only 32-bit CPUs here.
1031 */
1032 if (regs.ARM_cpsr & 0x20) {
1033 /*
1034 * Get the Thumb-mode system call number
1035 */
1036 scno = regs.ARM_r7;
1037 } else {
1038 /*
1039 * Get the ARM-mode system call number
1040 */
1041 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +00001042 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +00001043 if (errno)
1044 return -1;
1045
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001046 /* FIXME: bogus check? it is already done on entering before,
1047 * so we never can see it here?
1048 */
Roland McGrath0f87c492003-06-03 23:29:04 +00001049 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
1050 tcp->flags &= ~TCB_WAITEXECVE;
1051 return 0;
1052 }
1053
Roland McGrathf691bd22006-04-25 07:34:41 +00001054 /* Handle the EABI syscall convention. We do not
1055 bother converting structures between the two
1056 ABIs, but basic functionality should work even
1057 if strace and the traced program have different
1058 ABIs. */
1059 if (scno == 0xef000000) {
1060 scno = regs.ARM_r7;
1061 } else {
1062 if ((scno & 0x0ff00000) != 0x0f900000) {
1063 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1064 scno);
1065 return -1;
1066 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001067
Roland McGrathf691bd22006-04-25 07:34:41 +00001068 /*
1069 * Fixup the syscall number
1070 */
1071 scno &= 0x000fffff;
1072 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001073 }
Roland McGrath56703312008-05-20 01:35:55 +00001074 if (scno & 0x0f0000) {
1075 /*
1076 * Handle ARM specific syscall
1077 */
1078 set_personality(1);
1079 scno &= 0x0000ffff;
1080 } else
1081 set_personality(0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001082
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001083 if (exiting(tcp)) {
1084 fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
Roland McGrath0f87c492003-06-03 23:29:04 +00001085 tcp->flags &= ~TCB_INSYSCALL;
1086 }
1087 } else {
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001088 if (entering(tcp)) {
1089 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
Roland McGrath0f87c492003-06-03 23:29:04 +00001090 tcp->flags |= TCB_INSYSCALL;
1091 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001092 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001093# elif defined (M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001094 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001095 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001096# elif defined (LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001097 unsigned long long regs[38];
1098
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001099 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001100 return -1;
1101 a3 = regs[REG_A3];
1102 r2 = regs[REG_V0];
1103
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001104 if (entering(tcp)) {
Roland McGrath542c2c62008-05-20 01:11:56 +00001105 scno = r2;
1106
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001107 /* Check if this is the post-execve SIGTRAP. */
Roland McGrath542c2c62008-05-20 01:11:56 +00001108 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1109 tcp->flags &= ~TCB_WAITEXECVE;
1110 return 0;
1111 }
1112
1113 if (scno < 0 || scno > nsyscalls) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001114 if (a3 == 0 || a3 == -1) {
1115 if (debug)
1116 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001117 return 0;
1118 }
1119 }
1120 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001121# elif defined (MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001122 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001123 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001124 if (entering(tcp)) {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001125 if (upeek(tcp, REG_V0, &scno) < 0)
1126 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001127
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001128 /* Check if this is the post-execve SIGTRAP. */
Roland McGrath542c2c62008-05-20 01:11:56 +00001129 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1130 tcp->flags &= ~TCB_WAITEXECVE;
1131 return 0;
1132 }
1133
Wichert Akkermanf90da011999-10-31 21:15:38 +00001134 if (scno < 0 || scno > nsyscalls) {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001135 if (a3 == 0 || a3 == -1) {
1136 if (debug)
1137 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Wichert Akkermanf90da011999-10-31 21:15:38 +00001138 return 0;
1139 }
1140 }
1141 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001142 if (upeek(tcp, REG_V0, &r2) < 0)
1143 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001144 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001145# elif defined (ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001146 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001147 return -1;
1148
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001149 if (entering(tcp)) {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001150 if (upeek(tcp, REG_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001151 return -1;
1152
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001153 /* Check if this is the post-execve SIGTRAP. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1155 tcp->flags &= ~TCB_WAITEXECVE;
1156 return 0;
1157 }
1158
1159 /*
1160 * Do some sanity checks to figure out if it's
1161 * really a syscall entry
1162 */
1163 if (scno < 0 || scno > nsyscalls) {
1164 if (a3 == 0 || a3 == -1) {
1165 if (debug)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001166 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001167 return 0;
1168 }
1169 }
1170 }
1171 else {
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001172 if (upeek(tcp, REG_R0, &r0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001173 return -1;
1174 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001175# elif defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001176 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001177 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001178 return -1;
1179
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001180 /* If we are entering, then disassemble the syscall trap. */
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001181 if (entering(tcp)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001182 /* Retrieve the syscall trap instruction. */
1183 errno = 0;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001184# if defined(SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04001185 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001186 trap >>= 32;
Mike Frysinger8566c502009-10-12 11:05:14 -04001187# else
1188 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001189# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001190 if (errno)
1191 return -1;
1192
1193 /* Disassemble the trap to see what personality to use. */
1194 switch (trap) {
1195 case 0x91d02010:
1196 /* Linux/SPARC syscall trap. */
1197 set_personality(0);
1198 break;
Wichert Akkermandacfb6e1999-06-03 14:21:07 +00001199 case 0x91d0206d:
1200 /* Linux/SPARC64 syscall trap. */
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001201 set_personality(2);
1202 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001203 case 0x91d02000:
1204 /* SunOS syscall trap. (pers 1) */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001205 fprintf(stderr, "syscall: SunOS no support\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001206 return -1;
1207 case 0x91d02008:
1208 /* Solaris 2.x syscall trap. (per 2) */
1209 set_personality(1);
Roland McGrath761b5d72002-12-15 23:58:31 +00001210 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001211 case 0x91d02009:
1212 /* NetBSD/FreeBSD syscall trap. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001213 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001214 return -1;
1215 case 0x91d02027:
1216 /* Solaris 2.x gettimeofday */
1217 set_personality(1);
1218 break;
1219 default:
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001220 /* Check if this is the post-execve SIGTRAP. */
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001221 if (tcp->flags & TCB_WAITEXECVE) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001222 tcp->flags &= ~TCB_WAITEXECVE;
1223 return 0;
1224 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001225# if defined (SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001226 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001227# else
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001228 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001229# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001230 return -1;
1231 }
1232
1233 /* Extract the system call number from the registers. */
1234 if (trap == 0x91d02027)
1235 scno = 156;
1236 else
Mike Frysinger8566c502009-10-12 11:05:14 -04001237 scno = regs.u_regs[U_REG_G1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001238 if (scno == 0) {
Mike Frysinger8566c502009-10-12 11:05:14 -04001239 scno = regs.u_regs[U_REG_O0];
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001240 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 +00001241 }
1242 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001243# elif defined(HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001244 if (upeek(tcp, PT_GR20, &scno) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001245 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001246 if (entering(tcp)) {
1247 /* Check if this is the post-execve SIGTRAP. */
1248 if (tcp->flags & TCB_WAITEXECVE) {
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001249 tcp->flags &= ~TCB_WAITEXECVE;
1250 return 0;
1251 }
1252 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001253# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001254 /*
1255 * In the new syscall ABI, the system call number is in R3.
1256 */
1257 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1258 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001259
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001260 if (scno < 0) {
1261 /* Odd as it may seem, a glibc bug has been known to cause
1262 glibc to issue bogus negative syscall numbers. So for
1263 our purposes, make strace print what it *should* have been */
1264 long correct_scno = (scno & 0xff);
1265 if (debug)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001266 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001267 "Detected glibc bug: bogus system call"
1268 " number = %ld, correcting to %ld\n",
1269 scno,
1270 correct_scno);
1271 scno = correct_scno;
1272 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00001273
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001274 if (entering(tcp)) {
1275 /* Check if this is the post-execve SIGTRAP. */
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001276 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1277 tcp->flags &= ~TCB_WAITEXECVE;
1278 return 0;
1279 }
1280 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001281# elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001282 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001283 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001284 scno &= 0xFFFF;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001285
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001286 if (entering(tcp)) {
1287 /* Check if this is the post-execve SIGTRAP. */
Roland McGrathe1e584b2003-06-02 19:18:58 +00001288 if (tcp->flags & TCB_WAITEXECVE) {
1289 tcp->flags &= ~TCB_WAITEXECVE;
1290 return 0;
1291 }
1292 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001293# elif defined(CRISV10) || defined(CRISV32)
1294 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1295 return -1;
Chris Metcalfc8c66982009-12-28 10:00:15 -05001296# elif defined(TILE)
1297 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1298 return -1;
1299
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001300 if (entering(tcp)) {
1301 /* Check if this is the post-execve SIGTRAP. */
Chris Metcalfc8c66982009-12-28 10:00:15 -05001302 if (tcp->flags & TCB_WAITEXECVE) {
1303 tcp->flags &= ~TCB_WAITEXECVE;
1304 return 0;
1305 }
1306 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001307# elif defined(MICROBLAZE)
1308 if (upeek(tcp, 0, &scno) < 0)
1309 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001310# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001311#endif /* LINUX */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001312
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001313#ifdef SUNOS4
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001314 if (upeek(tcp, uoff(u_arg[7]), &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001315 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001316#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001317 /* new syscall ABI returns result in R0 */
1318 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1319 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001320#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001321 /* ABI defines result returned in r9 */
1322 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1323 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001324#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001325
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001326#ifdef USE_PROCFS
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001327# ifdef HAVE_PR_SYSCALL
John Hughes25299712001-03-06 10:10:06 +00001328 scno = tcp->status.PR_SYSCALL;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001329# else
1330# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001331 scno = tcp->status.PR_WHAT;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001332# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001333 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001334 perror("pread");
1335 return -1;
1336 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001337 switch (regs.r_eax) {
1338 case SYS_syscall:
1339 case SYS___syscall:
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001340 pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int));
1341 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001342 default:
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001343 scno = regs.r_eax;
1344 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001345 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001346# endif /* FREEBSD */
1347# endif /* !HAVE_PR_SYSCALL */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001348#endif /* USE_PROCFS */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001349
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001350 if (entering(tcp))
Wichert Akkerman5ae21ea2000-05-01 01:53:59 +00001351 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001352 return 1;
1353}
1354
Pavel Machek4dc3b142000-02-01 17:58:41 +00001355
Roland McGrath17352792005-06-07 23:21:26 +00001356long
Dmitry V. Levinbd136452011-02-18 23:19:47 +00001357known_scno(struct tcb *tcp)
Roland McGrath17352792005-06-07 23:21:26 +00001358{
1359 long scno = tcp->scno;
Dmitry V. Levinbd136452011-02-18 23:19:47 +00001360#if SUPPORTED_PERSONALITIES > 1
Roland McGrath17352792005-06-07 23:21:26 +00001361 if (scno >= 0 && scno < nsyscalls && sysent[scno].native_scno != 0)
1362 scno = sysent[scno].native_scno;
1363 else
Dmitry V. Levinbd136452011-02-18 23:19:47 +00001364#endif
Roland McGrath17352792005-06-07 23:21:26 +00001365 scno += NR_SYSCALL_BASE;
1366 return scno;
1367}
1368
Roland McGratheb9e2e82009-06-02 16:49:22 -07001369/* Called in trace_syscall() at each syscall entry and exit.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001370 * Returns:
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001371 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
Roland McGratheb9e2e82009-06-02 16:49:22 -07001372 * 1: ok, continue in trace_syscall().
1373 * other: error, trace_syscall() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001374 * ("????" etc) and bail out.
1375 */
Roland McGratha4d48532005-06-08 20:45:28 +00001376static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001377syscall_fixup(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001378{
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001379#ifdef USE_PROCFS
Roland McGrath17352792005-06-07 23:21:26 +00001380 int scno = known_scno(tcp);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001381
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001382 if (entering(tcp)) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001383 if (tcp->status.PR_WHY != PR_SYSENTRY) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001384 if (
1385 scno == SYS_fork
1386#ifdef SYS_vfork
1387 || scno == SYS_vfork
1388#endif /* SYS_vfork */
John Hughes4e36a812001-04-18 15:11:51 +00001389#ifdef SYS_fork1
1390 || scno == SYS_fork1
1391#endif /* SYS_fork1 */
1392#ifdef SYS_forkall
1393 || scno == SYS_forkall
1394#endif /* SYS_forkall */
1395#ifdef SYS_rfork1
1396 || scno == SYS_rfork1
1397#endif /* SYS_fork1 */
1398#ifdef SYS_rforkall
1399 || scno == SYS_rforkall
1400#endif /* SYS_rforkall */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001401 ) {
1402 /* We are returning in the child, fake it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001403 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001404 trace_syscall(tcp);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001405 tcp->status.PR_WHY = PR_SYSEXIT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001406 }
1407 else {
1408 fprintf(stderr, "syscall: missing entry\n");
1409 tcp->flags |= TCB_INSYSCALL;
1410 }
1411 }
1412 }
1413 else {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001414 if (tcp->status.PR_WHY != PR_SYSEXIT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001415 fprintf(stderr, "syscall: missing exit\n");
1416 tcp->flags &= ~TCB_INSYSCALL;
1417 }
1418 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001419#endif /* USE_PROCFS */
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001420
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001421#ifdef SUNOS4
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001422 if (entering(tcp)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001423 if (scno == 0) {
1424 fprintf(stderr, "syscall: missing entry\n");
1425 tcp->flags |= TCB_INSYSCALL;
1426 }
1427 }
1428 else {
1429 if (scno != 0) {
1430 if (debug) {
1431 /*
1432 * This happens when a signal handler
1433 * for a signal which interrupted a
1434 * a system call makes another system call.
1435 */
1436 fprintf(stderr, "syscall: missing exit\n");
1437 }
1438 tcp->flags &= ~TCB_INSYSCALL;
1439 }
1440 }
1441#endif /* SUNOS4 */
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001442
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001443#ifdef LINUX
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001444 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001445#if defined (I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001446 if (upeek(tcp, 4*EAX, &eax) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001447 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001448 if (eax != -ENOSYS && entering(tcp)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001449 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001450 fprintf(stderr, "not a syscall entry (eax = %ld)\n", eax);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001451 return 0;
1452 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001453#elif defined (X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001454 if (upeek(tcp, 8*RAX, &rax) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00001455 return -1;
Roland McGrath998fac72004-06-23 01:40:45 +00001456 if (current_personality == 1)
1457 rax = (long int)(int)rax; /* sign extend from 32 bits */
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001458 if (rax != -ENOSYS && entering(tcp)) {
Michal Ludvig0e035502002-09-23 15:41:01 +00001459 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001460 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
Michal Ludvig0e035502002-09-23 15:41:01 +00001461 return 0;
1462 }
Michal Ludvig10a88d02002-10-07 14:31:00 +00001463#elif defined (S390) || defined (S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001464 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001465 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001466 if (syscall_mode != -ENOSYS)
1467 syscall_mode = tcp->scno;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001468 if (gpr2 != syscall_mode && entering(tcp)) {
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001469 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001470 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001471 return 0;
1472 }
Roland McGrath96dc5142003-01-20 10:23:04 +00001473 else if (((tcp->flags & (TCB_INSYSCALL|TCB_WAITEXECVE))
1474 == (TCB_INSYSCALL|TCB_WAITEXECVE))
1475 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1476 /*
1477 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1478 * flag set for the post-execve SIGTRAP to see and reset.
1479 */
1480 gpr2 = 0;
1481 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001482#elif defined (POWERPC)
1483# define SO_MASK 0x10000000
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001484 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001485 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001486 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &result) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001487 return -1;
1488 if (flags & SO_MASK)
1489 result = -result;
1490#elif defined (M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001491 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001492 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001493 if (d0 != -ENOSYS && entering(tcp)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001494 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001495 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001496 return 0;
1497 }
1498#elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001499 /*
1500 * Nothing required
1501 */
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001502#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001503 if (upeek(tcp, PT_R0, &r0) < 0)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001504 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001505#elif defined (HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001506 if (upeek(tcp, PT_GR28, &r28) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001507 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001508#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001509 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001510 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001511 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001512 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001513 if (ia32 && r8 != -ENOSYS && entering(tcp)) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001514 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001515 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001516 return 0;
1517 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001518#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001519 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001520 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001521 if (r10 != -ENOSYS && entering(tcp)) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001522 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001523 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001524 return 0;
1525 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001526#elif defined(MICROBLAZE)
1527 if (upeek(tcp, 3 * 4, &r3) < 0)
1528 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001529 if (r3 != -ENOSYS && entering(tcp)) {
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001530 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001531 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001532 return 0;
1533 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001534#endif
1535#endif /* LINUX */
Pavel Machek4dc3b142000-02-01 17:58:41 +00001536 return 1;
1537}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001538
Roland McGrathc1e45922008-05-27 23:18:29 +00001539#ifdef LINUX
1540/*
1541 * Check the syscall return value register value for whether it is
1542 * a negated errno code indicating an error, or a success return value.
1543 */
1544static inline int
1545is_negated_errno(unsigned long int val)
1546{
1547 unsigned long int max = -(long int) nerrnos;
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001548# if SUPPORTED_PERSONALITIES > 1
Roland McGrathc1e45922008-05-27 23:18:29 +00001549 if (personality_wordsize[current_personality] < sizeof(val)) {
1550 val = (unsigned int) val;
1551 max = (unsigned int) max;
1552 }
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001553# endif
Roland McGrathc1e45922008-05-27 23:18:29 +00001554 return val > max;
1555}
1556#endif
1557
Roland McGratha4d48532005-06-08 20:45:28 +00001558static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001559get_error(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001560{
1561 int u_error = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001562#ifdef LINUX
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001563 int check_errno = 1;
1564 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
1565 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1566 check_errno = 0;
1567 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001568# if defined(S390) || defined(S390X)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001569 if (check_errno && is_negated_errno(gpr2)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001570 tcp->u_rval = -1;
1571 u_error = -gpr2;
1572 }
1573 else {
1574 tcp->u_rval = gpr2;
1575 u_error = 0;
1576 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001577# elif defined(I386)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001578 if (check_errno && is_negated_errno(eax)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001579 tcp->u_rval = -1;
1580 u_error = -eax;
1581 }
1582 else {
1583 tcp->u_rval = eax;
1584 u_error = 0;
1585 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001586# elif defined(X86_64)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001587 if (check_errno && is_negated_errno(rax)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001588 tcp->u_rval = -1;
1589 u_error = -rax;
1590 }
1591 else {
1592 tcp->u_rval = rax;
1593 u_error = 0;
1594 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001595# elif defined(IA64)
Roland McGrathc1e45922008-05-27 23:18:29 +00001596 if (ia32) {
1597 int err;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001598
Roland McGrathc1e45922008-05-27 23:18:29 +00001599 err = (int)r8;
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001600 if (check_errno && is_negated_errno(err)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001601 tcp->u_rval = -1;
1602 u_error = -err;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001603 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001604 else {
1605 tcp->u_rval = err;
1606 u_error = 0;
1607 }
1608 } else {
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001609 if (check_errno && r10) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001610 tcp->u_rval = -1;
1611 u_error = r8;
1612 } else {
1613 tcp->u_rval = r8;
1614 u_error = 0;
1615 }
1616 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001617# elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001618 if (check_errno && a3) {
1619 tcp->u_rval = -1;
1620 u_error = r2;
1621 } else {
1622 tcp->u_rval = r2;
1623 u_error = 0;
1624 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001625# elif defined(POWERPC)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001626 if (check_errno && is_negated_errno(result)) {
1627 tcp->u_rval = -1;
1628 u_error = -result;
1629 }
1630 else {
1631 tcp->u_rval = result;
1632 u_error = 0;
1633 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001634# elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001635 if (check_errno && is_negated_errno(d0)) {
1636 tcp->u_rval = -1;
1637 u_error = -d0;
1638 }
1639 else {
1640 tcp->u_rval = d0;
1641 u_error = 0;
1642 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001643# elif defined(ARM)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001644 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1645 tcp->u_rval = -1;
1646 u_error = -regs.ARM_r0;
1647 }
1648 else {
1649 tcp->u_rval = regs.ARM_r0;
1650 u_error = 0;
1651 }
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001652# elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001653 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1654 tcp->u_rval = -1;
1655 u_error = -regs.r12;
1656 }
1657 else {
1658 tcp->u_rval = regs.r12;
1659 u_error = 0;
1660 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001661# elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001662 if (check_errno && is_negated_errno(r0)) {
1663 tcp->u_rval = -1;
1664 u_error = -r0;
1665 } else {
1666 tcp->u_rval = r0;
1667 u_error = 0;
1668 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001669# elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001670 if (check_errno && a3) {
1671 tcp->u_rval = -1;
1672 u_error = r0;
1673 }
1674 else {
1675 tcp->u_rval = r0;
1676 u_error = 0;
1677 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001678# elif defined(SPARC)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001679 if (check_errno && regs.psr & PSR_C) {
1680 tcp->u_rval = -1;
1681 u_error = regs.u_regs[U_REG_O0];
1682 }
1683 else {
1684 tcp->u_rval = regs.u_regs[U_REG_O0];
1685 u_error = 0;
1686 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001687# elif defined(SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001688 if (check_errno && regs.tstate & 0x1100000000UL) {
1689 tcp->u_rval = -1;
1690 u_error = regs.u_regs[U_REG_O0];
1691 }
1692 else {
1693 tcp->u_rval = regs.u_regs[U_REG_O0];
1694 u_error = 0;
1695 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001696# elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001697 if (check_errno && is_negated_errno(r28)) {
1698 tcp->u_rval = -1;
1699 u_error = -r28;
1700 }
1701 else {
1702 tcp->u_rval = r28;
1703 u_error = 0;
1704 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001705# elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001706 /* interpret R0 as return value or error number */
1707 if (check_errno && is_negated_errno(r0)) {
1708 tcp->u_rval = -1;
1709 u_error = -r0;
1710 }
1711 else {
1712 tcp->u_rval = r0;
1713 u_error = 0;
1714 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001715# elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001716 /* interpret result as return value or error number */
1717 if (check_errno && is_negated_errno(r9)) {
1718 tcp->u_rval = -1;
1719 u_error = -r9;
1720 }
1721 else {
1722 tcp->u_rval = r9;
1723 u_error = 0;
1724 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001725# elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001726 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1727 tcp->u_rval = -1;
1728 u_error = -r10;
1729 }
1730 else {
1731 tcp->u_rval = r10;
1732 u_error = 0;
1733 }
Chris Metcalfc8c66982009-12-28 10:00:15 -05001734# elif defined(TILE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001735 long rval;
1736 /* interpret result as return value or error number */
1737 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1738 return -1;
1739 if (check_errno && rval < 0 && rval > -nerrnos) {
1740 tcp->u_rval = -1;
1741 u_error = -rval;
1742 }
1743 else {
1744 tcp->u_rval = rval;
1745 u_error = 0;
1746 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001747# elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001748 /* interpret result as return value or error number */
1749 if (check_errno && is_negated_errno(r3)) {
1750 tcp->u_rval = -1;
1751 u_error = -r3;
1752 }
1753 else {
1754 tcp->u_rval = r3;
1755 u_error = 0;
1756 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001757# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001758#endif /* LINUX */
1759#ifdef SUNOS4
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001760 /* get error code from user struct */
1761 if (upeek(tcp, uoff(u_error), &u_error) < 0)
1762 return -1;
1763 u_error >>= 24; /* u_error is a char */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001764
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001765 /* get system call return value */
1766 if (upeek(tcp, uoff(u_rval1), &tcp->u_rval) < 0)
1767 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001768#endif /* SUNOS4 */
1769#ifdef SVR4
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001770# ifdef SPARC
1771 /* Judicious guessing goes a long way. */
1772 if (tcp->status.pr_reg[R_PSR] & 0x100000) {
1773 tcp->u_rval = -1;
1774 u_error = tcp->status.pr_reg[R_O0];
1775 }
1776 else {
1777 tcp->u_rval = tcp->status.pr_reg[R_O0];
1778 u_error = 0;
1779 }
1780# endif /* SPARC */
1781# ifdef I386
1782 /* Wanna know how to kill an hour single-stepping? */
1783 if (tcp->status.PR_REG[EFL] & 0x1) {
1784 tcp->u_rval = -1;
1785 u_error = tcp->status.PR_REG[EAX];
1786 }
1787 else {
1788 tcp->u_rval = tcp->status.PR_REG[EAX];
1789# ifdef HAVE_LONG_LONG
1790 tcp->u_lrval =
1791 ((unsigned long long) tcp->status.PR_REG[EDX] << 32) +
1792 tcp->status.PR_REG[EAX];
1793# endif
1794 u_error = 0;
1795 }
1796# endif /* I386 */
1797# ifdef X86_64
1798 /* Wanna know how to kill an hour single-stepping? */
1799 if (tcp->status.PR_REG[EFLAGS] & 0x1) {
1800 tcp->u_rval = -1;
1801 u_error = tcp->status.PR_REG[RAX];
1802 }
1803 else {
1804 tcp->u_rval = tcp->status.PR_REG[RAX];
1805 u_error = 0;
1806 }
1807# endif /* X86_64 */
1808# ifdef MIPS
1809 if (tcp->status.pr_reg[CTX_A3]) {
1810 tcp->u_rval = -1;
1811 u_error = tcp->status.pr_reg[CTX_V0];
1812 }
1813 else {
1814 tcp->u_rval = tcp->status.pr_reg[CTX_V0];
1815 u_error = 0;
1816 }
1817# endif /* MIPS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001818#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001819#ifdef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001820 if (regs.r_eflags & PSL_C) {
1821 tcp->u_rval = -1;
1822 u_error = regs.r_eax;
1823 } else {
1824 tcp->u_rval = regs.r_eax;
1825 tcp->u_lrval =
1826 ((unsigned long long) regs.r_edx << 32) + regs.r_eax;
1827 u_error = 0;
1828 }
Roland McGrath761b5d72002-12-15 23:58:31 +00001829#endif /* FREEBSD */
Pavel Machek4dc3b142000-02-01 17:58:41 +00001830 tcp->u_error = u_error;
1831 return 1;
1832}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001833
Roland McGrathb69f81b2002-12-21 23:25:18 +00001834int
Denys Vlasenko12014262011-05-30 14:00:14 +02001835force_result(struct tcb *tcp, int error, long rval)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001836{
1837#ifdef LINUX
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001838# if defined(S390) || defined(S390X)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001839 gpr2 = error ? -error : rval;
Roland McGrathb69f81b2002-12-21 23:25:18 +00001840 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_GPR2, gpr2) < 0)
1841 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001842# elif defined(I386)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001843 eax = error ? -error : rval;
1844 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(EAX * 4), eax) < 0)
1845 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001846# elif defined(X86_64)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001847 rax = error ? -error : rval;
Roland McGrath998fac72004-06-23 01:40:45 +00001848 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(RAX * 8), rax) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001849 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001850# elif defined(IA64)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001851 if (ia32) {
1852 r8 = error ? -error : rval;
1853 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0)
1854 return -1;
1855 }
1856 else {
1857 if (error) {
1858 r8 = error;
1859 r10 = -1;
1860 }
1861 else {
1862 r8 = rval;
1863 r10 = 0;
1864 }
1865 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0 ||
1866 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R10), r10) < 0)
1867 return -1;
1868 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001869# elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001870 r0 = error ? -error : rval;
1871 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_R0, r0) < 0)
1872 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001873# elif defined(MIPS)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001874 if (error) {
1875 r2 = error;
1876 a3 = -1;
1877 }
1878 else {
1879 r2 = rval;
1880 a3 = 0;
1881 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001882 /* PTRACE_POKEUSER is OK even for n32 since rval is only a long. */
Roland McGrathb69f81b2002-12-21 23:25:18 +00001883 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1884 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), r2) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001885 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001886# elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001887 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001888 return -1;
1889 if (error) {
1890 flags |= SO_MASK;
1891 result = error;
1892 }
1893 else {
1894 flags &= ~SO_MASK;
1895 result = rval;
1896 }
Roland McGratheb285352003-01-14 09:59:00 +00001897 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_CCR), flags) < 0 ||
1898 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_R3), result) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001899 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001900# elif defined(M68K)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001901 d0 = error ? -error : rval;
1902 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_D0), d0) < 0)
1903 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001904# elif defined(ARM)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001905 regs.ARM_r0 = error ? -error : rval;
1906 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*0), regs.ARM_r0) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001907 return -1;
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001908# elif defined(AVR32)
1909 regs.r12 = error ? -error : rval;
1910 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_R12, regs.r12) < 0)
1911 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001912# elif defined(ALPHA)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001913 if (error) {
1914 a3 = -1;
1915 r0 = error;
1916 }
1917 else {
1918 a3 = 0;
1919 r0 = rval;
1920 }
1921 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1922 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R0), r0) < 0)
1923 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001924# elif defined(SPARC)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001925 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1926 return -1;
1927 if (error) {
Mike Frysinger8566c502009-10-12 11:05:14 -04001928 regs.psr |= PSR_C;
1929 regs.u_regs[U_REG_O0] = error;
Roland McGrathb69f81b2002-12-21 23:25:18 +00001930 }
1931 else {
Mike Frysinger8566c502009-10-12 11:05:14 -04001932 regs.psr &= ~PSR_C;
1933 regs.u_regs[U_REG_O0] = rval;
Roland McGrathb69f81b2002-12-21 23:25:18 +00001934 }
1935 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1936 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001937# elif defined(SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001938 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1939 return -1;
1940 if (error) {
Mike Frysinger8566c502009-10-12 11:05:14 -04001941 regs.tstate |= 0x1100000000UL;
1942 regs.u_regs[U_REG_O0] = error;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001943 }
1944 else {
Mike Frysinger8566c502009-10-12 11:05:14 -04001945 regs.tstate &= ~0x1100000000UL;
1946 regs.u_regs[U_REG_O0] = rval;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00001947 }
1948 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1949 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001950# elif defined(HPPA)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001951 r28 = error ? -error : rval;
1952 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR28), r28) < 0)
1953 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001954# elif defined(SH)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001955 r0 = error ? -error : rval;
1956 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*REG_REG0), r0) < 0)
1957 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001958# elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001959 r9 = error ? -error : rval;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001960 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_GENERAL(9), r9) < 0)
1961 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001962# endif
Roland McGrathb69f81b2002-12-21 23:25:18 +00001963#endif /* LINUX */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001964
Roland McGrathb69f81b2002-12-21 23:25:18 +00001965#ifdef SUNOS4
Roland McGratheb9e2e82009-06-02 16:49:22 -07001966 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_error),
1967 error << 24) < 0 ||
1968 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_rval1), rval) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00001969 return -1;
1970#endif /* SUNOS4 */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001971
Roland McGrathb69f81b2002-12-21 23:25:18 +00001972#ifdef SVR4
1973 /* XXX no clue */
1974 return -1;
1975#endif /* SVR4 */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001976
Roland McGrathb69f81b2002-12-21 23:25:18 +00001977#ifdef FREEBSD
1978 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001979 perror("pread");
1980 return -1;
1981 }
Roland McGrathb69f81b2002-12-21 23:25:18 +00001982 if (error) {
1983 regs.r_eflags |= PSL_C;
1984 regs.r_eax = error;
1985 }
1986 else {
1987 regs.r_eflags &= ~PSL_C;
1988 regs.r_eax = rval;
1989 }
1990 if (pwrite(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001991 perror("pwrite");
1992 return -1;
1993 }
Roland McGrathb69f81b2002-12-21 23:25:18 +00001994#endif /* FREEBSD */
1995
1996 /* All branches reach here on success (only). */
1997 tcp->u_error = error;
1998 tcp->u_rval = rval;
1999 return 0;
2000}
2001
Roland McGratha4d48532005-06-08 20:45:28 +00002002static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002003syscall_enter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002004{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002005#ifdef LINUX
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002006# if defined(S390) || defined(S390X)
2007 int i;
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002008 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002009 tcp->u_nargs = sysent[tcp->scno].nargs;
2010 else
2011 tcp->u_nargs = MAX_ARGS;
2012 for (i = 0; i < tcp->u_nargs; i++) {
2013 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
2014 return -1;
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00002015 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002016# elif defined(ALPHA)
2017 int i;
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002018 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002019 tcp->u_nargs = sysent[tcp->scno].nargs;
2020 else
2021 tcp->u_nargs = MAX_ARGS;
2022 for (i = 0; i < tcp->u_nargs; i++) {
2023 /* WTA: if scno is out-of-bounds this will bomb. Add range-check
2024 * for scno somewhere above here!
2025 */
2026 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
2027 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002028 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002029# elif defined(IA64)
2030 if (!ia32) {
2031 unsigned long *out0, cfm, sof, sol, i;
2032 long rbs_end;
2033 /* be backwards compatible with kernel < 2.4.4... */
2034# ifndef PT_RBS_END
2035# define PT_RBS_END PT_AR_BSP
2036# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002037
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002038 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
2039 return -1;
2040 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00002041 return -1;
2042
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002043 sof = (cfm >> 0) & 0x7f;
2044 sol = (cfm >> 7) & 0x7f;
2045 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
2046
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002047 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002048 tcp->u_nargs = sysent[tcp->scno].nargs;
2049 else
2050 tcp->u_nargs = MAX_ARGS;
2051 for (i = 0; i < tcp->u_nargs; ++i) {
2052 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
2053 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
2054 return -1;
2055 }
2056 } else {
2057 int i;
2058
2059 if (/* EBX = out0 */
2060 upeek(tcp, PT_R11, (long *) &tcp->u_arg[0]) < 0
2061 /* ECX = out1 */
2062 || upeek(tcp, PT_R9, (long *) &tcp->u_arg[1]) < 0
2063 /* EDX = out2 */
2064 || upeek(tcp, PT_R10, (long *) &tcp->u_arg[2]) < 0
2065 /* ESI = out3 */
2066 || upeek(tcp, PT_R14, (long *) &tcp->u_arg[3]) < 0
2067 /* EDI = out4 */
2068 || upeek(tcp, PT_R15, (long *) &tcp->u_arg[4]) < 0
2069 /* EBP = out5 */
2070 || upeek(tcp, PT_R13, (long *) &tcp->u_arg[5]) < 0)
2071 return -1;
2072
2073 for (i = 0; i < 6; ++i)
2074 /* truncate away IVE sign-extension */
2075 tcp->u_arg[i] &= 0xffffffff;
2076
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002077 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002078 tcp->u_nargs = sysent[tcp->scno].nargs;
2079 else
2080 tcp->u_nargs = 5;
2081 }
2082# elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
2083 /* N32 and N64 both use up to six registers. */
2084 unsigned long long regs[38];
2085 int i, nargs;
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002086 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002087 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
2088 else
2089 nargs = tcp->u_nargs = MAX_ARGS;
2090
2091 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
2092 return -1;
2093
2094 for (i = 0; i < nargs; i++) {
2095 tcp->u_arg[i] = regs[REG_A0 + i];
2096# if defined(LINUX_MIPSN32)
2097 tcp->ext_arg[i] = regs[REG_A0 + i];
2098# endif
2099 }
2100# elif defined(MIPS)
2101 long sp;
2102 int i, nargs;
2103
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002104 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002105 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
2106 else
2107 nargs = tcp->u_nargs = MAX_ARGS;
2108 if (nargs > 4) {
2109 if (upeek(tcp, REG_SP, &sp) < 0)
2110 return -1;
2111 for (i = 0; i < 4; i++) {
2112 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
2113 return -1;
2114 }
2115 umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]),
2116 (char *)(tcp->u_arg + 4));
2117 } else {
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002118 for (i = 0; i < nargs; i++) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002119 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002120 return -1;
2121 }
2122 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002123# elif defined(POWERPC)
2124# ifndef PT_ORIG_R3
2125# define PT_ORIG_R3 34
2126# endif
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002127 int i, nargs;
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002128 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002129 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002130 else
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002131 nargs = tcp->u_nargs = MAX_ARGS;
2132 for (i = 0; i < nargs; i++) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002133 if (upeek(tcp, (i==0) ?
2134 (sizeof(unsigned long) * PT_ORIG_R3) :
2135 ((i+PT_R3) * sizeof(unsigned long)),
2136 &tcp->u_arg[i]) < 0)
2137 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002138 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002139# elif defined(SPARC) || defined(SPARC64)
2140 int i;
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002141 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002142 tcp->u_nargs = sysent[tcp->scno].nargs;
2143 else
2144 tcp->u_nargs = MAX_ARGS;
2145 for (i = 0; i < tcp->u_nargs; i++)
2146 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
2147# elif defined(HPPA)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002148 int i, nargs;
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002149 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002150 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002151 else
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002152 nargs = tcp->u_nargs = MAX_ARGS;
2153 for (i = 0; i < nargs; i++) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002154 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
2155 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00002156 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002157# elif defined(ARM)
2158 int i;
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002159 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002160 tcp->u_nargs = sysent[tcp->scno].nargs;
2161 else
2162 tcp->u_nargs = MAX_ARGS;
2163 for (i = 0; i < tcp->u_nargs; i++)
2164 tcp->u_arg[i] = regs.uregs[i];
2165# elif defined(AVR32)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002166 tcp->u_nargs = sysent[tcp->scno].nargs;
2167 tcp->u_arg[0] = regs.r12;
2168 tcp->u_arg[1] = regs.r11;
2169 tcp->u_arg[2] = regs.r10;
2170 tcp->u_arg[3] = regs.r9;
2171 tcp->u_arg[4] = regs.r5;
2172 tcp->u_arg[5] = regs.r3;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002173# elif defined(BFIN)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002174 int i, nargs;
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02002175 static const int argreg[] = { PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5 };
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00002176
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002177 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002178 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002179 else
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002180 nargs = tcp->u_nargs = ARRAY_SIZE(argreg);
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002181
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002182 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002183 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
2184 return -1;
2185# elif defined(SH)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002186 int i, nargs;
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02002187 static const int syscall_regs[] = {
2188 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6), 4 * (REG_REG0+7),
2189 4 * (REG_REG0 ), 4 * (REG_REG0+1), 4 * (REG_REG0+2)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002190 };
2191
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002192 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
2193 for (i = 0; i < nargs; i++) {
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02002194 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002195 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002196 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002197# elif defined(SH64)
2198 int i;
2199 /* Registers used by SH5 Linux system calls for parameters */
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02002200 static const int syscall_regs[] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00002201
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002202 /*
2203 * TODO: should also check that the number of arguments encoded
2204 * in the trap number matches the number strace expects.
2205 */
2206 /*
2207 assert(sysent[tcp->scno].nargs < ARRAY_SIZE(syscall_regs));
2208 */
Roland McGrathe1e584b2003-06-02 19:18:58 +00002209
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002210 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
2211 for (i = 0; i < nargs; i++) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002212 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
2213 return -1;
2214 }
2215# elif defined(X86_64)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002216 int i, nargs;
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02002217 static const int argreg[SUPPORTED_PERSONALITIES][MAX_ARGS] = {
2218 { 8 * RDI, 8 * RSI, 8 * RDX, 8 * R10, 8 * R8 , 8 * R9 }, /* x86-64 ABI */
2219 { 8 * RBX, 8 * RCX, 8 * RDX, 8 * RSI, 8 * RDI, 8 * RBP } /* i386 ABI */
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002220 };
2221
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002222 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002223 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002224 else
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002225 nargs = tcp->u_nargs = MAX_ARGS;
2226 for (i = 0; i < nargs; i++) {
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02002227 if (upeek(tcp, argreg[current_personality][i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002228 return -1;
Roland McGrathe1e584b2003-06-02 19:18:58 +00002229 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002230# elif defined(MICROBLAZE)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002231 int i, nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002232 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002233 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002234 else
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002235 nargs = tcp->u_nargs = 0;
2236 for (i = 0; i < nargs; i++) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002237 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
2238 return -1;
2239 }
2240# elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002241 int i, nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002242 static const int crisregs[] = {
2243 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02002244 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002245 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00002246
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002247 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002248 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002249 else
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002250 nargs = tcp->u_nargs = 0;
2251 for (i = 0; i < nargs; i++) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002252 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
2253 return -1;
Michal Ludvig0e035502002-09-23 15:41:01 +00002254 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002255# elif defined(TILE)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002256 int i, nargs;
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002257 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002258 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002259 else
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002260 nargs = tcp->u_nargs = MAX_ARGS;
2261 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002262 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
2263 return -1;
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02002264 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002265# elif defined(M68K)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002266 int i, nargs;
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002267 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002268 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002269 else
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002270 nargs = tcp->u_nargs = MAX_ARGS;
2271 for (i = 0; i < nargs; i++) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002272 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
2273 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002274 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002275# else /* Other architecture (like i386) (32bits specific) */
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002276 int i, nargs;
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002277 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002278 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002279 else
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002280 nargs = tcp->u_nargs = MAX_ARGS;
2281 for (i = 0; i < nargs; i++) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002282 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
2283 return -1;
Chris Metcalfc8c66982009-12-28 10:00:15 -05002284 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002285# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002286#endif /* LINUX */
2287#ifdef SUNOS4
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002288 int i, nargs;
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002289 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002290 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002291 else
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002292 nargs = tcp->u_nargs = MAX_ARGS;
2293 for (i = 0; i < nargs; i++) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002294 struct user *u;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002295
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002296 if (upeek(tcp, uoff(u_arg[0]) +
2297 (i * sizeof(u->u_arg[0])), &tcp->u_arg[i]) < 0)
2298 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002299 }
2300#endif /* SUNOS4 */
2301#ifdef SVR4
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002302# ifdef MIPS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002303 /*
2304 * SGI is broken: even though it has pr_sysarg, it doesn't
2305 * set them on system call entry. Get a clue.
2306 */
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002307 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002308 tcp->u_nargs = sysent[tcp->scno].nargs;
2309 else
2310 tcp->u_nargs = tcp->status.pr_nsysarg;
2311 if (tcp->u_nargs > 4) {
2312 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002313 4 * sizeof(tcp->u_arg[0]));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002314 umoven(tcp, tcp->status.pr_reg[CTX_SP] + 16,
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002315 (tcp->u_nargs - 4) * sizeof(tcp->u_arg[0]), (char *) (tcp->u_arg + 4));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002316 }
2317 else {
2318 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002319 tcp->u_nargs * sizeof(tcp->u_arg[0]));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002320 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002321# elif UNIXWARE >= 2
John Hughes25299712001-03-06 10:10:06 +00002322 /*
2323 * Like SGI, UnixWare doesn't set pr_sysarg until system call exit
2324 */
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002325 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
John Hughes25299712001-03-06 10:10:06 +00002326 tcp->u_nargs = sysent[tcp->scno].nargs;
2327 else
2328 tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;
2329 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002330 tcp->u_nargs * sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2331# elif defined(HAVE_PR_SYSCALL)
2332 int i;
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002333 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002334 tcp->u_nargs = sysent[tcp->scno].nargs;
2335 else
2336 tcp->u_nargs = tcp->status.pr_nsysarg;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002337 for (i = 0; i < tcp->u_nargs; i++)
2338 tcp->u_arg[i] = tcp->status.pr_sysarg[i];
2339# elif defined(I386)
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002340 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002341 tcp->u_nargs = sysent[tcp->scno].nargs;
2342 else
2343 tcp->u_nargs = 5;
Denys Vlasenko4660fe62011-06-09 01:32:23 +02002344 if (tcp->u_nargs > 0)
2345 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002346 tcp->u_nargs * sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2347# else
John Hughes25299712001-03-06 10:10:06 +00002348 I DONT KNOW WHAT TO DO
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002349# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002350#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002351#ifdef FREEBSD
2352 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2353 sysent[tcp->scno].nargs > tcp->status.val)
2354 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002355 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002356 tcp->u_nargs = tcp->status.val;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002357 if (tcp->u_nargs < 0)
2358 tcp->u_nargs = 0;
2359 if (tcp->u_nargs > MAX_ARGS)
2360 tcp->u_nargs = MAX_ARGS;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002361 switch (regs.r_eax) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002362 case SYS___syscall:
2363 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2364 regs.r_esp + sizeof(int) + sizeof(quad_t));
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002365 break;
2366 case SYS_syscall:
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002367 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2368 regs.r_esp + 2 * sizeof(int));
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002369 break;
2370 default:
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002371 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2372 regs.r_esp + sizeof(int));
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002373 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002374 }
2375#endif /* FREEBSD */
Pavel Machek4dc3b142000-02-01 17:58:41 +00002376 return 1;
2377}
2378
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002379static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002380trace_syscall_entering(struct tcb *tcp)
2381{
2382 int res, scno_good;
2383
2384 scno_good = res = get_scno(tcp);
2385 if (res == 0)
2386 return res;
2387 if (res == 1)
2388 res = syscall_fixup(tcp);
2389 if (res == 0)
2390 return res;
2391 if (res == 1)
2392 res = syscall_enter(tcp);
2393 if (res == 0)
2394 return res;
2395
2396 if (res != 1) {
2397 printleader(tcp);
2398 tcp->flags &= ~TCB_REPRINT;
2399 tcp_last = tcp;
2400 if (scno_good != 1)
2401 tprintf("????" /* anti-trigraph gap */ "(");
2402 else if (tcp->scno >= nsyscalls || tcp->scno < 0)
2403 tprintf("syscall_%lu(", tcp->scno);
2404 else
2405 tprintf("%s(", sysent[tcp->scno].sys_name);
2406 /*
2407 * " <unavailable>" will be added later by the code which
2408 * detects ptrace errors.
2409 */
2410 goto ret;
2411 }
2412
2413 switch (known_scno(tcp)) {
2414#ifdef SYS_socket_subcall
2415 case SYS_socketcall:
2416 decode_subcall(tcp, SYS_socket_subcall,
2417 SYS_socket_nsubcalls, deref_style);
2418 break;
2419#endif
2420#ifdef SYS_ipc_subcall
2421 case SYS_ipc:
2422 decode_subcall(tcp, SYS_ipc_subcall,
2423 SYS_ipc_nsubcalls, shift_style);
2424 break;
2425#endif
2426#ifdef SVR4
2427#ifdef SYS_pgrpsys_subcall
2428 case SYS_pgrpsys:
2429 decode_subcall(tcp, SYS_pgrpsys_subcall,
2430 SYS_pgrpsys_nsubcalls, shift_style);
2431 break;
2432#endif /* SYS_pgrpsys_subcall */
2433#ifdef SYS_sigcall_subcall
2434 case SYS_sigcall:
2435 decode_subcall(tcp, SYS_sigcall_subcall,
2436 SYS_sigcall_nsubcalls, mask_style);
2437 break;
2438#endif /* SYS_sigcall_subcall */
2439 case SYS_msgsys:
2440 decode_subcall(tcp, SYS_msgsys_subcall,
2441 SYS_msgsys_nsubcalls, shift_style);
2442 break;
2443 case SYS_shmsys:
2444 decode_subcall(tcp, SYS_shmsys_subcall,
2445 SYS_shmsys_nsubcalls, shift_style);
2446 break;
2447 case SYS_semsys:
2448 decode_subcall(tcp, SYS_semsys_subcall,
2449 SYS_semsys_nsubcalls, shift_style);
2450 break;
2451 case SYS_sysfs:
2452 decode_subcall(tcp, SYS_sysfs_subcall,
2453 SYS_sysfs_nsubcalls, shift_style);
2454 break;
2455 case SYS_spcall:
2456 decode_subcall(tcp, SYS_spcall_subcall,
2457 SYS_spcall_nsubcalls, shift_style);
2458 break;
2459#ifdef SYS_context_subcall
2460 case SYS_context:
2461 decode_subcall(tcp, SYS_context_subcall,
2462 SYS_context_nsubcalls, shift_style);
2463 break;
2464#endif /* SYS_context_subcall */
2465#ifdef SYS_door_subcall
2466 case SYS_door:
2467 decode_subcall(tcp, SYS_door_subcall,
2468 SYS_door_nsubcalls, door_style);
2469 break;
2470#endif /* SYS_door_subcall */
2471#ifdef SYS_kaio_subcall
2472 case SYS_kaio:
2473 decode_subcall(tcp, SYS_kaio_subcall,
2474 SYS_kaio_nsubcalls, shift_style);
2475 break;
2476#endif
2477#endif /* SVR4 */
2478#ifdef FREEBSD
2479 case SYS_msgsys:
2480 case SYS_shmsys:
2481 case SYS_semsys:
2482 decode_subcall(tcp, 0, 0, table_style);
2483 break;
2484#endif
2485#ifdef SUNOS4
2486 case SYS_semsys:
2487 decode_subcall(tcp, SYS_semsys_subcall,
2488 SYS_semsys_nsubcalls, shift_style);
2489 break;
2490 case SYS_msgsys:
2491 decode_subcall(tcp, SYS_msgsys_subcall,
2492 SYS_msgsys_nsubcalls, shift_style);
2493 break;
2494 case SYS_shmsys:
2495 decode_subcall(tcp, SYS_shmsys_subcall,
2496 SYS_shmsys_nsubcalls, shift_style);
2497 break;
2498#endif
2499 }
2500
2501 internal_syscall(tcp);
2502
2503 if ((tcp->scno >= 0 && tcp->scno < nsyscalls &&
2504 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
2505 (tracing_paths && !pathtrace_match(tcp))) {
2506 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
2507 return 0;
2508 }
2509
2510 tcp->flags &= ~TCB_FILTERED;
2511
2512 if (cflag == CFLAG_ONLY_STATS) {
2513 res = 0;
2514 goto ret;
2515 }
2516
2517 printleader(tcp);
2518 tcp->flags &= ~TCB_REPRINT;
2519 tcp_last = tcp;
2520 if (tcp->scno >= nsyscalls || tcp->scno < 0)
2521 tprintf("syscall_%lu(", tcp->scno);
2522 else
2523 tprintf("%s(", sysent[tcp->scno].sys_name);
2524 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2525 ((qual_flags[tcp->scno] & QUAL_RAW) &&
2526 sysent[tcp->scno].sys_func != sys_exit))
2527 res = printargs(tcp);
2528 else
2529 res = (*sysent[tcp->scno].sys_func)(tcp);
2530
2531 if (fflush(tcp->outf) == EOF)
2532 return -1;
2533 ret:
2534 tcp->flags |= TCB_INSYSCALL;
2535 /* Measure the entrance time as late as possible to avoid errors. */
2536 if (dtime || cflag)
2537 gettimeofday(&tcp->etime, NULL);
2538 return res;
2539}
2540
2541static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002542trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002543{
2544 int sys_res;
2545 struct timeval tv;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002546 int res, scno_good;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002547 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002548
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002549 /* Measure the exit time as early as possible to avoid errors. */
2550 if (dtime || cflag)
2551 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002552
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002553 /* BTW, why we don't just memorize syscall no. on entry
2554 * in tcp->something?
2555 */
2556 scno_good = res = get_scno(tcp);
2557 if (res == 0)
2558 return res;
2559 if (res == 1)
2560 res = syscall_fixup(tcp);
2561 if (res == 0)
2562 return res;
2563 if (res == 1)
2564 res = get_error(tcp);
2565 if (res == 0)
2566 return res;
2567 if (res == 1)
2568 internal_syscall(tcp);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002569
Grant Edwards8a082772011-04-07 20:25:40 +00002570 if (res == 1 && filtered(tcp)) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002571 goto ret;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002572 }
2573
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002574 if (tcp->flags & TCB_REPRINT) {
2575 printleader(tcp);
2576 tprintf("<... ");
2577 if (scno_good != 1)
2578 tprintf("????");
2579 else if (tcp->scno >= nsyscalls || tcp->scno < 0)
2580 tprintf("syscall_%lu", tcp->scno);
2581 else
2582 tprintf("%s", sysent[tcp->scno].sys_name);
2583 tprintf(" resumed> ");
2584 }
2585
2586 if (cflag) {
2587 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002588 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002589 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002590 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002591 }
2592 }
2593
2594 if (res != 1) {
2595 tprintf(") ");
2596 tabto(acolumn);
2597 tprintf("= ? <unavailable>");
2598 printtrailer();
2599 tcp->flags &= ~TCB_INSYSCALL;
2600 return res;
2601 }
2602
2603 if (tcp->scno >= nsyscalls || tcp->scno < 0
2604 || (qual_flags[tcp->scno] & QUAL_RAW))
2605 sys_res = printargs(tcp);
2606 else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002607 /* FIXME: not_failing_only (IOW, option -z) is broken:
2608 * failure of syscall is known only after syscall return.
2609 * Thus we end up with something like this on, say, ENOENT:
2610 * open("doesnt_exist", O_RDONLY <unfinished ...>
2611 * {next syscall decode}
2612 * whereas the intended result is that open(...) line
2613 * is not shown at all.
2614 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002615 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002616 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002617 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2618 }
2619
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002620 tprintf(") ");
2621 tabto(acolumn);
Denys Vlasenko3b738812011-08-22 02:06:35 +02002622 u_error = tcp->u_error;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002623 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2624 qual_flags[tcp->scno] & QUAL_RAW) {
2625 if (u_error)
2626 tprintf("= -1 (errno %ld)", u_error);
2627 else
2628 tprintf("= %#lx", tcp->u_rval);
2629 }
2630 else if (!(sys_res & RVAL_NONE) && u_error) {
2631 switch (u_error) {
2632#ifdef LINUX
2633 case ERESTARTSYS:
2634 tprintf("= ? ERESTARTSYS (To be restarted)");
2635 break;
2636 case ERESTARTNOINTR:
2637 tprintf("= ? ERESTARTNOINTR (To be restarted)");
2638 break;
2639 case ERESTARTNOHAND:
2640 tprintf("= ? ERESTARTNOHAND (To be restarted)");
2641 break;
2642 case ERESTART_RESTARTBLOCK:
2643 tprintf("= ? ERESTART_RESTARTBLOCK (To be restarted)");
2644 break;
2645#endif /* LINUX */
2646 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002647 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002648 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002649 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002650 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002651 strerror(u_error));
2652 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002653 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002654 strerror(u_error));
2655 break;
2656 }
2657 if ((sys_res & RVAL_STR) && tcp->auxstr)
2658 tprintf(" (%s)", tcp->auxstr);
2659 }
2660 else {
2661 if (sys_res & RVAL_NONE)
2662 tprintf("= ?");
2663 else {
2664 switch (sys_res & RVAL_MASK) {
2665 case RVAL_HEX:
2666 tprintf("= %#lx", tcp->u_rval);
2667 break;
2668 case RVAL_OCTAL:
2669 tprintf("= %#lo", tcp->u_rval);
2670 break;
2671 case RVAL_UDECIMAL:
2672 tprintf("= %lu", tcp->u_rval);
2673 break;
2674 case RVAL_DECIMAL:
2675 tprintf("= %ld", tcp->u_rval);
2676 break;
2677#ifdef HAVE_LONG_LONG
2678 case RVAL_LHEX:
2679 tprintf("= %#llx", tcp->u_lrval);
2680 break;
2681 case RVAL_LOCTAL:
2682 tprintf("= %#llo", tcp->u_lrval);
2683 break;
2684 case RVAL_LUDECIMAL:
2685 tprintf("= %llu", tcp->u_lrval);
2686 break;
2687 case RVAL_LDECIMAL:
2688 tprintf("= %lld", tcp->u_lrval);
2689 break;
2690#endif
2691 default:
2692 fprintf(stderr,
2693 "invalid rval format\n");
2694 break;
2695 }
2696 }
2697 if ((sys_res & RVAL_STR) && tcp->auxstr)
2698 tprintf(" (%s)", tcp->auxstr);
2699 }
2700 if (dtime) {
2701 tv_sub(&tv, &tv, &tcp->etime);
2702 tprintf(" <%ld.%06ld>",
2703 (long) tv.tv_sec, (long) tv.tv_usec);
2704 }
2705 printtrailer();
2706
2707 dumpio(tcp);
2708 if (fflush(tcp->outf) == EOF)
2709 return -1;
Denys Vlasenko3b738812011-08-22 02:06:35 +02002710 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002711 tcp->flags &= ~TCB_INSYSCALL;
2712 return 0;
2713}
2714
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002715int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002716trace_syscall(struct tcb *tcp)
2717{
2718 return exiting(tcp) ?
2719 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2720}
2721
2722int
Denys Vlasenko12014262011-05-30 14:00:14 +02002723printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002724{
2725 if (entering(tcp)) {
2726 int i;
2727
2728 for (i = 0; i < tcp->u_nargs; i++)
2729 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
2730 }
2731 return 0;
2732}
2733
2734long
Denys Vlasenko12014262011-05-30 14:00:14 +02002735getrval2(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002736{
2737 long val = -1;
2738
2739#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002740#if defined (SPARC) || defined (SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04002741 struct pt_regs regs;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002742 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002743 return -1;
Mike Frysinger8566c502009-10-12 11:05:14 -04002744 val = regs.u_regs[U_REG_O1];
Roland McGrath6b1d43e2003-03-31 01:05:01 +00002745#elif defined(SH)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002746 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
Roland McGrath6b1d43e2003-03-31 01:05:01 +00002747 return -1;
Roland McGrathb4ce1762004-03-01 20:30:48 +00002748#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002749 if (upeek(tcp, PT_R9, &val) < 0)
Roland McGrathb4ce1762004-03-01 20:30:48 +00002750 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002751#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002752#endif /* LINUX */
2753
2754#ifdef SUNOS4
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002755 if (upeek(tcp, uoff(u_rval2), &val) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002756 return -1;
2757#endif /* SUNOS4 */
2758
2759#ifdef SVR4
2760#ifdef SPARC
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002761 val = tcp->status.PR_REG[R_O1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002762#endif /* SPARC */
2763#ifdef I386
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002764 val = tcp->status.PR_REG[EDX];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002765#endif /* I386 */
Michal Ludvig0e035502002-09-23 15:41:01 +00002766#ifdef X86_64
2767 val = tcp->status.PR_REG[RDX];
2768#endif /* X86_64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002769#ifdef MIPS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002770 val = tcp->status.PR_REG[CTX_V1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002771#endif /* MIPS */
2772#endif /* SVR4 */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002773
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002774#ifdef FREEBSD
2775 struct reg regs;
2776 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
2777 val = regs.r_edx;
Roland McGrath761b5d72002-12-15 23:58:31 +00002778#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002779 return val;
2780}
2781
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +00002782#ifdef SUNOS4
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002783/*
2784 * Apparently, indirect system calls have already be converted by ptrace(2),
2785 * so if you see "indir" this program has gone astray.
2786 */
2787int
Denys Vlasenko12014262011-05-30 14:00:14 +02002788sys_indir(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002789{
2790 int i, scno, nargs;
2791
2792 if (entering(tcp)) {
Denys Vlasenko5d645812011-08-20 12:48:18 +02002793 scno = tcp->u_arg[0];
2794 if (scno > nsyscalls) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002795 fprintf(stderr, "Bogus syscall: %u\n", scno);
2796 return 0;
2797 }
2798 nargs = sysent[scno].nargs;
2799 tprintf("%s", sysent[scno].sys_name);
2800 for (i = 0; i < nargs; i++)
2801 tprintf(", %#lx", tcp->u_arg[i+1]);
2802 }
2803 return 0;
2804}
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +00002805#endif /* SUNOS4 */
Dmitry V. Levin2e55ff42008-09-03 01:02:46 +00002806
2807int
2808is_restart_error(struct tcb *tcp)
2809{
2810#ifdef LINUX
2811 if (!syserror(tcp))
2812 return 0;
2813 switch (tcp->u_error) {
2814 case ERESTARTSYS:
2815 case ERESTARTNOINTR:
2816 case ERESTARTNOHAND:
2817 case ERESTART_RESTARTBLOCK:
2818 return 1;
2819 default:
2820 break;
2821 }
2822#endif /* LINUX */
2823 return 0;
2824}