blob: a3b6080901f87b13d64ba16b72243522bef53e75 [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 */
Denys Vlasenko9a36ae52011-08-24 16:47:32 +0200747#ifndef USE_PROCFS
748static
749#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000750int
Denys Vlasenko9a36ae52011-08-24 16:47:32 +0200751get_scno_on_sysenter(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000752{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000753 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000754
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000755#ifdef LINUX
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000756# if defined(S390) || defined(S390X)
Roland McGrath96dc5142003-01-20 10:23:04 +0000757 if (tcp->flags & TCB_WAITEXECVE) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200758 /* This is the post-execve SIGTRAP. */
Roland McGrath96dc5142003-01-20 10:23:04 +0000759 tcp->flags &= ~TCB_WAITEXECVE;
760 return 0;
761 }
Roland McGrath2f924ca2003-06-26 22:23:28 +0000762
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000763 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200764 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000765
766 if (syscall_mode != -ENOSYS) {
767 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000768 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000769 */
770 scno = syscall_mode;
771 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000772 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000773 * Old style of "passing" the scno via the SVC instruction.
774 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000775 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200776 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200777 static const int gpr_offset[16] = {
778 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
779 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
780 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
781 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
782 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000783
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000784 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000785 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000786 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000787 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000788 if (errno) {
789 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000790 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000791 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000792
793 /*
794 * We have to check if the SVC got executed directly or via an
795 * EXECUTE instruction. In case of EXECUTE it is necessary to do
796 * instruction decoding to derive the system call number.
797 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
798 * so that this doesn't work if a SVC opcode is part of an EXECUTE
799 * opcode. Since there is no way to find out the opcode size this
800 * is the best we can do...
801 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000802 if ((opcode & 0xff00) == 0x0a00) {
803 /* SVC opcode */
804 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000805 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000806 else {
807 /* SVC got executed by EXECUTE instruction */
808
809 /*
810 * Do instruction decoding of EXECUTE. If you really want to
811 * understand this, read the Principles of Operations.
812 */
813 svc_addr = (void *) (opcode & 0xfff);
814
815 tmp = 0;
816 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000817 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000818 return -1;
819 svc_addr += tmp;
820
821 tmp = 0;
822 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000823 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000824 return -1;
825 svc_addr += tmp;
826
Denys Vlasenkofb036672009-01-23 16:30:26 +0000827 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000828 if (errno)
829 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000830# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000831 scno >>= 48;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000832# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000833 scno >>= 16;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000834# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000835 tmp = 0;
836 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000837 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000838 return -1;
839
840 scno = (scno | tmp) & 0xff;
841 }
842 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000843# elif defined (POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000844 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000845 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200846 /* Check if this is the post-execve SIGTRAP. */
847 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
848 tcp->flags &= ~TCB_WAITEXECVE;
849 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000850 }
Andreas Schwabd69fa492010-07-12 21:39:57 +0200851# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200852 /* TODO: speed up strace by not doing this at every syscall.
853 * We only need to do it after execve.
854 */
855 int currpers;
856 long val;
857 int pid = tcp->pid;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200858
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200859 /* Check for 64/32 bit mode. */
860 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
861 return -1;
862 /* SF is bit 0 of MSR */
863 if (val < 0)
864 currpers = 0;
865 else
866 currpers = 1;
867 if (currpers != current_personality) {
868 static const char *const names[] = {"64 bit", "32 bit"};
869 set_personality(currpers);
870 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
871 pid, names[current_personality]);
Andreas Schwabd69fa492010-07-12 21:39:57 +0200872 }
873# endif
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000874# elif defined(AVR32)
875 /*
876 * Read complete register set in one go.
877 */
878 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
879 return -1;
880
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200881 scno = regs.r8;
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000882
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200883 /* Check if this is the post-execve SIGTRAP. */
884 if (tcp->flags & TCB_WAITEXECVE) {
885 tcp->flags &= ~TCB_WAITEXECVE;
886 return 0;
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000887 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000888# elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000889 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000890 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000891# elif defined (I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000892 if (upeek(tcp, 4*ORIG_EAX, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000893 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000894# elif defined (X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000895 if (upeek(tcp, 8*ORIG_RAX, &scno) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +0000896 return -1;
897
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200898 /* TODO: speed up strace by not doing this at every syscall.
899 * We only need to do it after execve.
900 */
901 int currpers;
902 long val;
903 int pid = tcp->pid;
Michal Ludvig0e035502002-09-23 15:41:01 +0000904
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200905 /* Check CS register value. On x86-64 linux it is:
906 * 0x33 for long mode (64 bit)
907 * 0x23 for compatibility mode (32 bit)
908 * It takes only one ptrace and thus doesn't need
909 * to be cached.
910 */
911 if (upeek(tcp, 8*CS, &val) < 0)
912 return -1;
913 switch (val) {
914 case 0x23: currpers = 1; break;
915 case 0x33: currpers = 0; break;
916 default:
917 fprintf(stderr, "Unknown value CS=0x%02X while "
918 "detecting personality of process "
919 "PID=%d\n", (int)val, pid);
920 currpers = current_personality;
921 break;
922 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000923# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200924 /* This version analyzes the opcode of a syscall instruction.
925 * (int 0x80 on i386 vs. syscall on x86-64)
926 * It works, but is too complicated.
927 */
928 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +0000929
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200930 if (upeek(tcp, 8*RIP, &rip) < 0)
931 perror("upeek(RIP)");
Roland McGrath761b5d72002-12-15 23:58:31 +0000932
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200933 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
934 rip -= 2;
935 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +0000936
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200937 call = ptrace(PTRACE_PEEKTEXT, pid, (char *)rip, (char *)0);
938 if (errno)
939 fprintf(stderr, "ptrace_peektext failed: %s\n",
940 strerror(errno));
941 switch (call & 0xffff) {
942 /* x86-64: syscall = 0x0f 0x05 */
943 case 0x050f: currpers = 0; break;
944 /* i386: int 0x80 = 0xcd 0x80 */
945 case 0x80cd: currpers = 1; break;
946 default:
947 currpers = current_personality;
948 fprintf(stderr,
949 "Unknown syscall opcode (0x%04X) while "
950 "detecting personality of process "
951 "PID=%d\n", (int)call, pid);
952 break;
953 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000954# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200955 if (currpers != current_personality) {
956 static const char *const names[] = {"64 bit", "32 bit"};
957 set_personality(currpers);
958 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
959 pid, names[current_personality]);
Roland McGrath761b5d72002-12-15 23:58:31 +0000960 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000961# elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000962# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200963 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000964 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200965 if (ia32) {
966 if (upeek(tcp, PT_R1, &scno) < 0) /* orig eax */
967 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000968 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200969 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000970 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200971 }
972 /* Check if this is the post-execve SIGTRAP. */
973 if (tcp->flags & TCB_WAITEXECVE) {
974 tcp->flags &= ~TCB_WAITEXECVE;
975 return 0;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000976 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000977# elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +0000978 /*
979 * Read complete register set in one go.
980 */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000981 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +0000982 return -1;
983
984 /*
985 * We only need to grab the syscall number on syscall entry.
986 */
987 if (regs.ARM_ip == 0) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200988 /* Check if this is the post-execve SIGTRAP. */
989 if (tcp->flags & TCB_WAITEXECVE) {
990 tcp->flags &= ~TCB_WAITEXECVE;
991 return 0;
Roland McGrath9bc63402007-11-01 21:42:18 +0000992 }
993
Roland McGrath0f87c492003-06-03 23:29:04 +0000994 /*
995 * Note: we only deal with only 32-bit CPUs here.
996 */
997 if (regs.ARM_cpsr & 0x20) {
998 /*
999 * Get the Thumb-mode system call number
1000 */
1001 scno = regs.ARM_r7;
1002 } else {
1003 /*
1004 * Get the ARM-mode system call number
1005 */
1006 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +00001007 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +00001008 if (errno)
1009 return -1;
1010
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001011 /* FIXME: bogus check? it is already done before,
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001012 * so we never can see it here?
1013 */
Roland McGrath0f87c492003-06-03 23:29:04 +00001014 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
1015 tcp->flags &= ~TCB_WAITEXECVE;
1016 return 0;
1017 }
1018
Roland McGrathf691bd22006-04-25 07:34:41 +00001019 /* Handle the EABI syscall convention. We do not
1020 bother converting structures between the two
1021 ABIs, but basic functionality should work even
1022 if strace and the traced program have different
1023 ABIs. */
1024 if (scno == 0xef000000) {
1025 scno = regs.ARM_r7;
1026 } else {
1027 if ((scno & 0x0ff00000) != 0x0f900000) {
1028 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1029 scno);
1030 return -1;
1031 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001032
Roland McGrathf691bd22006-04-25 07:34:41 +00001033 /*
1034 * Fixup the syscall number
1035 */
1036 scno &= 0x000fffff;
1037 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001038 }
Roland McGrath56703312008-05-20 01:35:55 +00001039 if (scno & 0x0f0000) {
1040 /*
1041 * Handle ARM specific syscall
1042 */
1043 set_personality(1);
1044 scno &= 0x0000ffff;
1045 } else
1046 set_personality(0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001047
Roland McGrath0f87c492003-06-03 23:29:04 +00001048 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001049 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1050 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001051 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001052# elif defined (M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001053 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001054 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001055# elif defined (LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001056 unsigned long long regs[38];
1057
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001058 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001059 return -1;
1060 a3 = regs[REG_A3];
1061 r2 = regs[REG_V0];
1062
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001063 scno = r2;
Roland McGrath542c2c62008-05-20 01:11:56 +00001064
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001065 /* Check if this is the post-execve SIGTRAP. */
1066 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1067 tcp->flags &= ~TCB_WAITEXECVE;
1068 return 0;
1069 }
1070
1071 if (scno < 0 || scno > nsyscalls) {
1072 if (a3 == 0 || a3 == -1) {
1073 if (debug)
1074 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001075 return 0;
1076 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001077 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001078# elif defined (MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001079 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001080 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001081 if (upeek(tcp, REG_V0, &scno) < 0)
1082 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001083
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001084 /* Check if this is the post-execve SIGTRAP. */
1085 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1086 tcp->flags &= ~TCB_WAITEXECVE;
1087 return 0;
1088 }
1089
1090 if (scno < 0 || scno > nsyscalls) {
1091 if (a3 == 0 || a3 == -1) {
1092 if (debug)
1093 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001094 return 0;
1095 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001096 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001097# elif defined (ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001098 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001099 return -1;
1100
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001101 if (upeek(tcp, REG_R0, &scno) < 0)
1102 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001103
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001104 /* Check if this is the post-execve SIGTRAP. */
1105 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1106 tcp->flags &= ~TCB_WAITEXECVE;
1107 return 0;
1108 }
1109
1110 /*
1111 * Do some sanity checks to figure out if it's
1112 * really a syscall entry
1113 */
1114 if (scno < 0 || scno > nsyscalls) {
1115 if (a3 == 0 || a3 == -1) {
1116 if (debug)
1117 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001118 return 0;
1119 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001120 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001121# elif defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001122 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001123 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001124 return -1;
1125
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001126 /* Disassemble the syscall trap. */
1127 /* Retrieve the syscall trap instruction. */
1128 errno = 0;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001129# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001130 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1131 trap >>= 32;
Mike Frysinger8566c502009-10-12 11:05:14 -04001132# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001133 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001134# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001135 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001136 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001137
1138 /* Disassemble the trap to see what personality to use. */
1139 switch (trap) {
1140 case 0x91d02010:
1141 /* Linux/SPARC syscall trap. */
1142 set_personality(0);
1143 break;
1144 case 0x91d0206d:
1145 /* Linux/SPARC64 syscall trap. */
1146 set_personality(2);
1147 break;
1148 case 0x91d02000:
1149 /* SunOS syscall trap. (pers 1) */
1150 fprintf(stderr, "syscall: SunOS no support\n");
1151 return -1;
1152 case 0x91d02008:
1153 /* Solaris 2.x syscall trap. (per 2) */
1154 set_personality(1);
1155 break;
1156 case 0x91d02009:
1157 /* NetBSD/FreeBSD syscall trap. */
1158 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1159 return -1;
1160 case 0x91d02027:
1161 /* Solaris 2.x gettimeofday */
1162 set_personality(1);
1163 break;
1164 default:
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001165 /* Check if this is the post-execve SIGTRAP. */
1166 if (tcp->flags & TCB_WAITEXECVE) {
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001167 tcp->flags &= ~TCB_WAITEXECVE;
1168 return 0;
1169 }
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001170# if defined (SPARC64)
1171 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
1172# else
1173 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
1174# endif
1175 return -1;
1176 }
1177
1178 /* Extract the system call number from the registers. */
1179 if (trap == 0x91d02027)
1180 scno = 156;
1181 else
1182 scno = regs.u_regs[U_REG_G1];
1183 if (scno == 0) {
1184 scno = regs.u_regs[U_REG_O0];
1185 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1186 }
1187# elif defined(HPPA)
1188 if (upeek(tcp, PT_GR20, &scno) < 0)
1189 return -1;
1190 /* Check if this is the post-execve SIGTRAP. */
1191 if (tcp->flags & TCB_WAITEXECVE) {
1192 tcp->flags &= ~TCB_WAITEXECVE;
1193 return 0;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001194 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001195# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001196 /*
1197 * In the new syscall ABI, the system call number is in R3.
1198 */
1199 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1200 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001201
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001202 if (scno < 0) {
1203 /* Odd as it may seem, a glibc bug has been known to cause
1204 glibc to issue bogus negative syscall numbers. So for
1205 our purposes, make strace print what it *should* have been */
1206 long correct_scno = (scno & 0xff);
1207 if (debug)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001208 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001209 "Detected glibc bug: bogus system call"
1210 " number = %ld, correcting to %ld\n",
1211 scno,
1212 correct_scno);
1213 scno = correct_scno;
1214 }
Wichert Akkermanccef6372002-05-01 16:39:22 +00001215
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001216 /* Check if this is the post-execve SIGTRAP. */
1217 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1218 tcp->flags &= ~TCB_WAITEXECVE;
1219 return 0;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001220 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001221# elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001222 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001223 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001224 scno &= 0xFFFF;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001225
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001226 /* Check if this is the post-execve SIGTRAP. */
1227 if (tcp->flags & TCB_WAITEXECVE) {
1228 tcp->flags &= ~TCB_WAITEXECVE;
1229 return 0;
Roland McGrathe1e584b2003-06-02 19:18:58 +00001230 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001231# elif defined(CRISV10) || defined(CRISV32)
1232 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1233 return -1;
Chris Metcalfc8c66982009-12-28 10:00:15 -05001234# elif defined(TILE)
1235 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1236 return -1;
1237
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001238 /* Check if this is the post-execve SIGTRAP. */
1239 if (tcp->flags & TCB_WAITEXECVE) {
1240 tcp->flags &= ~TCB_WAITEXECVE;
1241 return 0;
Chris Metcalfc8c66982009-12-28 10:00:15 -05001242 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001243# elif defined(MICROBLAZE)
1244 if (upeek(tcp, 0, &scno) < 0)
1245 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001246# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001247#endif /* LINUX */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001248
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001249#ifdef SUNOS4
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001250 if (upeek(tcp, uoff(u_arg[7]), &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001251 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001252#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001253 /* new syscall ABI returns result in R0 */
1254 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1255 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001256#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001257 /* ABI defines result returned in r9 */
1258 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1259 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001260#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001261
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001262#ifdef USE_PROCFS
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001263# ifdef HAVE_PR_SYSCALL
John Hughes25299712001-03-06 10:10:06 +00001264 scno = tcp->status.PR_SYSCALL;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001265# else
1266# ifndef FREEBSD
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001267 scno = tcp->status.PR_WHAT;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001268# else
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001269 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001270 perror("pread");
1271 return -1;
1272 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001273 switch (regs.r_eax) {
1274 case SYS_syscall:
1275 case SYS___syscall:
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001276 pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int));
1277 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001278 default:
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001279 scno = regs.r_eax;
1280 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001281 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001282# endif /* FREEBSD */
1283# endif /* !HAVE_PR_SYSCALL */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001284#endif /* USE_PROCFS */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001285
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001286 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001287 return 1;
1288}
1289
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02001290/* Returns:
1291 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1292 * 1: ok, continue in trace_syscall().
1293 * other: error, trace_syscall() should print error indicator
1294 * ("????" etc) and bail out.
1295 */
1296static int
1297get_scno_on_sysexit(struct tcb *tcp)
1298{
1299 long scno = 0;
1300
1301#ifdef LINUX
1302# if defined(S390) || defined(S390X)
1303 if (tcp->flags & TCB_WAITEXECVE) {
1304 /*
1305 * When the execve system call completes successfully, the
1306 * new process still has -ENOSYS (old style) or __NR_execve
1307 * (new style) in gpr2. We cannot recover the scno again
1308 * by disassembly, because the image that executed the
1309 * syscall is gone now. Fortunately, we don't want it. We
1310 * leave the flag set so that syscall_fixup can fake the
1311 * result.
1312 */
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001313 return 1;
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02001314 }
1315
1316 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
1317 return -1;
1318
1319 if (syscall_mode != -ENOSYS) {
1320 /*
1321 * Since kernel version 2.5.44 the scno gets passed in gpr2.
1322 */
1323 scno = syscall_mode;
1324 } else {
1325 /*
1326 * Old style of "passing" the scno via the SVC instruction.
1327 */
1328
1329 long opcode, offset_reg, tmp;
1330 void * svc_addr;
1331 static const int gpr_offset[16] = {
1332 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
1333 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
1334 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
1335 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
1336 };
1337
1338 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
1339 return -1;
1340 errno = 0;
1341 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
1342 if (errno) {
1343 perror("peektext(pc-oneword)");
1344 return -1;
1345 }
1346
1347 /*
1348 * We have to check if the SVC got executed directly or via an
1349 * EXECUTE instruction. In case of EXECUTE it is necessary to do
1350 * instruction decoding to derive the system call number.
1351 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
1352 * so that this doesn't work if a SVC opcode is part of an EXECUTE
1353 * opcode. Since there is no way to find out the opcode size this
1354 * is the best we can do...
1355 */
1356
1357 if ((opcode & 0xff00) == 0x0a00) {
1358 /* SVC opcode */
1359 scno = opcode & 0xff;
1360 }
1361 else {
1362 /* SVC got executed by EXECUTE instruction */
1363
1364 /*
1365 * Do instruction decoding of EXECUTE. If you really want to
1366 * understand this, read the Principles of Operations.
1367 */
1368 svc_addr = (void *) (opcode & 0xfff);
1369
1370 tmp = 0;
1371 offset_reg = (opcode & 0x000f0000) >> 16;
1372 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
1373 return -1;
1374 svc_addr += tmp;
1375
1376 tmp = 0;
1377 offset_reg = (opcode & 0x0000f000) >> 12;
1378 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
1379 return -1;
1380 svc_addr += tmp;
1381
1382 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
1383 if (errno)
1384 return -1;
1385# if defined(S390X)
1386 scno >>= 48;
1387# else
1388 scno >>= 16;
1389# endif
1390 tmp = 0;
1391 offset_reg = (opcode & 0x00f00000) >> 20;
1392 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
1393 return -1;
1394
1395 scno = (scno | tmp) & 0xff;
1396 }
1397 }
1398# elif defined (POWERPC)
1399 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
1400 return -1;
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02001401# elif defined(AVR32)
1402 /*
1403 * Read complete register set in one go.
1404 */
1405 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1406 return -1;
1407
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02001408# elif defined(BFIN)
1409 if (upeek(tcp, PT_ORIG_P0, &scno))
1410 return -1;
1411# elif defined (I386)
1412 if (upeek(tcp, 4*ORIG_EAX, &scno) < 0)
1413 return -1;
1414# elif defined (X86_64)
1415 if (upeek(tcp, 8*ORIG_RAX, &scno) < 0)
1416 return -1;
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02001417# elif defined(IA64)
1418# define IA64_PSR_IS ((long)1 << 34)
1419 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1420 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001421 if (upeek(tcp, PT_R8, &r8) < 0)
1422 return -1;
1423 if (upeek(tcp, PT_R10, &r10) < 0)
1424 return -1;
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02001425# elif defined (ARM)
1426 /*
1427 * Read complete register set in one go.
1428 */
1429 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1430 return -1;
1431
1432 /*
1433 * We only need to grab the syscall number on syscall entry.
1434 */
1435 if (regs.ARM_ip == 0) {
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02001436 /*
1437 * Note: we only deal with only 32-bit CPUs here.
1438 */
1439 if (regs.ARM_cpsr & 0x20) {
1440 /*
1441 * Get the Thumb-mode system call number
1442 */
1443 scno = regs.ARM_r7;
1444 } else {
1445 /*
1446 * Get the ARM-mode system call number
1447 */
1448 errno = 0;
1449 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
1450 if (errno)
1451 return -1;
1452
1453 /* FIXME: bogus check? it is already done on entering before,
1454 * so we never can see it here?
1455 */
1456 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
1457 tcp->flags &= ~TCB_WAITEXECVE;
1458 return 0;
1459 }
1460
1461 /* Handle the EABI syscall convention. We do not
1462 bother converting structures between the two
1463 ABIs, but basic functionality should work even
1464 if strace and the traced program have different
1465 ABIs. */
1466 if (scno == 0xef000000) {
1467 scno = regs.ARM_r7;
1468 } else {
1469 if ((scno & 0x0ff00000) != 0x0f900000) {
1470 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1471 scno);
1472 return -1;
1473 }
1474
1475 /*
1476 * Fixup the syscall number
1477 */
1478 scno &= 0x000fffff;
1479 }
1480 }
1481 if (scno & 0x0f0000) {
1482 /*
1483 * Handle ARM specific syscall
1484 */
1485 set_personality(1);
1486 scno &= 0x0000ffff;
1487 } else
1488 set_personality(0);
1489
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001490 fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
1491 tcp->flags &= ~TCB_INSYSCALL;
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02001492 }
1493# elif defined (M68K)
1494 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
1495 return -1;
1496# elif defined (LINUX_MIPSN32)
1497 unsigned long long regs[38];
1498
1499 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1500 return -1;
1501 a3 = regs[REG_A3];
1502 r2 = regs[REG_V0];
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02001503# elif defined (MIPS)
1504 if (upeek(tcp, REG_A3, &a3) < 0)
1505 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001506 if (upeek(tcp, REG_V0, &r2) < 0)
1507 return -1;
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02001508# elif defined (ALPHA)
1509 if (upeek(tcp, REG_A3, &a3) < 0)
1510 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001511 if (upeek(tcp, REG_R0, &r0) < 0)
1512 return -1;
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02001513# elif defined (SPARC) || defined (SPARC64)
1514 /* Everything we need is in the current register set. */
1515 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1516 return -1;
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02001517# elif defined(HPPA)
1518 if (upeek(tcp, PT_GR20, &scno) < 0)
1519 return -1;
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02001520# elif defined(SH)
1521 /*
1522 * In the new syscall ABI, the system call number is in R3.
1523 */
1524 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1525 return -1;
1526
1527 if (scno < 0) {
1528 /* Odd as it may seem, a glibc bug has been known to cause
1529 glibc to issue bogus negative syscall numbers. So for
1530 our purposes, make strace print what it *should* have been */
1531 long correct_scno = (scno & 0xff);
1532 if (debug)
1533 fprintf(stderr,
1534 "Detected glibc bug: bogus system call"
1535 " number = %ld, correcting to %ld\n",
1536 scno,
1537 correct_scno);
1538 scno = correct_scno;
1539 }
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02001540# elif defined(SH64)
1541 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
1542 return -1;
1543 scno &= 0xFFFF;
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02001544# elif defined(CRISV10) || defined(CRISV32)
1545 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1546 return -1;
1547# elif defined(TILE)
1548 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1549 return -1;
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02001550# elif defined(MICROBLAZE)
1551 if (upeek(tcp, 0, &scno) < 0)
1552 return -1;
1553# endif
1554#endif /* LINUX */
1555
1556#ifdef SUNOS4
1557 if (upeek(tcp, uoff(u_arg[7]), &scno) < 0)
1558 return -1;
1559#elif defined(SH)
1560 /* new syscall ABI returns result in R0 */
1561 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1562 return -1;
1563#elif defined(SH64)
1564 /* ABI defines result returned in r9 */
1565 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1566 return -1;
1567#endif
1568
1569#ifdef USE_PROCFS
1570# ifdef HAVE_PR_SYSCALL
1571 scno = tcp->status.PR_SYSCALL;
1572# else
1573# ifndef FREEBSD
1574 scno = tcp->status.PR_WHAT;
1575# else
1576 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1577 perror("pread");
1578 return -1;
1579 }
1580 switch (regs.r_eax) {
1581 case SYS_syscall:
1582 case SYS___syscall:
1583 pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int));
1584 break;
1585 default:
1586 scno = regs.r_eax;
1587 break;
1588 }
1589# endif /* FREEBSD */
1590# endif /* !HAVE_PR_SYSCALL */
1591#endif /* USE_PROCFS */
1592
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02001593 return 1;
1594}
Pavel Machek4dc3b142000-02-01 17:58:41 +00001595
Roland McGrath17352792005-06-07 23:21:26 +00001596long
Dmitry V. Levinbd136452011-02-18 23:19:47 +00001597known_scno(struct tcb *tcp)
Roland McGrath17352792005-06-07 23:21:26 +00001598{
1599 long scno = tcp->scno;
Dmitry V. Levinbd136452011-02-18 23:19:47 +00001600#if SUPPORTED_PERSONALITIES > 1
Roland McGrath17352792005-06-07 23:21:26 +00001601 if (scno >= 0 && scno < nsyscalls && sysent[scno].native_scno != 0)
1602 scno = sysent[scno].native_scno;
1603 else
Dmitry V. Levinbd136452011-02-18 23:19:47 +00001604#endif
Roland McGrath17352792005-06-07 23:21:26 +00001605 scno += NR_SYSCALL_BASE;
1606 return scno;
1607}
1608
Roland McGratheb9e2e82009-06-02 16:49:22 -07001609/* Called in trace_syscall() at each syscall entry and exit.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001610 * Returns:
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001611 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
Roland McGratheb9e2e82009-06-02 16:49:22 -07001612 * 1: ok, continue in trace_syscall().
1613 * other: error, trace_syscall() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001614 * ("????" etc) and bail out.
1615 */
Roland McGratha4d48532005-06-08 20:45:28 +00001616static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001617syscall_fixup(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001618{
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001619#ifdef USE_PROCFS
Roland McGrath17352792005-06-07 23:21:26 +00001620 int scno = known_scno(tcp);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001621
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001622 if (entering(tcp)) {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001623 if (tcp->status.PR_WHY != PR_SYSENTRY) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001624 if (
1625 scno == SYS_fork
1626#ifdef SYS_vfork
1627 || scno == SYS_vfork
1628#endif /* SYS_vfork */
John Hughes4e36a812001-04-18 15:11:51 +00001629#ifdef SYS_fork1
1630 || scno == SYS_fork1
1631#endif /* SYS_fork1 */
1632#ifdef SYS_forkall
1633 || scno == SYS_forkall
1634#endif /* SYS_forkall */
1635#ifdef SYS_rfork1
1636 || scno == SYS_rfork1
1637#endif /* SYS_fork1 */
1638#ifdef SYS_rforkall
1639 || scno == SYS_rforkall
1640#endif /* SYS_rforkall */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001641 ) {
1642 /* We are returning in the child, fake it. */
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001643 tcp->status.PR_WHY = PR_SYSENTRY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001644 trace_syscall(tcp);
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001645 tcp->status.PR_WHY = PR_SYSEXIT;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001646 }
1647 else {
1648 fprintf(stderr, "syscall: missing entry\n");
1649 tcp->flags |= TCB_INSYSCALL;
1650 }
1651 }
1652 }
1653 else {
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00001654 if (tcp->status.PR_WHY != PR_SYSEXIT) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001655 fprintf(stderr, "syscall: missing exit\n");
1656 tcp->flags &= ~TCB_INSYSCALL;
1657 }
1658 }
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00001659#endif /* USE_PROCFS */
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001660
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001661#ifdef SUNOS4
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001662 if (entering(tcp)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001663 if (scno == 0) {
1664 fprintf(stderr, "syscall: missing entry\n");
1665 tcp->flags |= TCB_INSYSCALL;
1666 }
1667 }
1668 else {
1669 if (scno != 0) {
1670 if (debug) {
1671 /*
1672 * This happens when a signal handler
1673 * for a signal which interrupted a
1674 * a system call makes another system call.
1675 */
1676 fprintf(stderr, "syscall: missing exit\n");
1677 }
1678 tcp->flags &= ~TCB_INSYSCALL;
1679 }
1680 }
1681#endif /* SUNOS4 */
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001682
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001683#ifdef LINUX
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001684 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001685#if defined (I386)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001686 if (upeek(tcp, 4*EAX, &eax) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001687 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001688 if (eax != -ENOSYS && entering(tcp)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001689 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001690 fprintf(stderr, "not a syscall entry (eax = %ld)\n", eax);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001691 return 0;
1692 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001693#elif defined (X86_64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001694 if (upeek(tcp, 8*RAX, &rax) < 0)
Michal Ludvig0e035502002-09-23 15:41:01 +00001695 return -1;
Roland McGrath998fac72004-06-23 01:40:45 +00001696 if (current_personality == 1)
1697 rax = (long int)(int)rax; /* sign extend from 32 bits */
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001698 if (rax != -ENOSYS && entering(tcp)) {
Michal Ludvig0e035502002-09-23 15:41:01 +00001699 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001700 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
Michal Ludvig0e035502002-09-23 15:41:01 +00001701 return 0;
1702 }
Michal Ludvig10a88d02002-10-07 14:31:00 +00001703#elif defined (S390) || defined (S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001704 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001705 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001706 if (syscall_mode != -ENOSYS)
1707 syscall_mode = tcp->scno;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001708 if (gpr2 != syscall_mode && entering(tcp)) {
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001709 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001710 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001711 return 0;
1712 }
Roland McGrath96dc5142003-01-20 10:23:04 +00001713 else if (((tcp->flags & (TCB_INSYSCALL|TCB_WAITEXECVE))
1714 == (TCB_INSYSCALL|TCB_WAITEXECVE))
1715 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1716 /*
1717 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1718 * flag set for the post-execve SIGTRAP to see and reset.
1719 */
1720 gpr2 = 0;
1721 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001722#elif defined (POWERPC)
1723# define SO_MASK 0x10000000
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001724 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001725 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001726 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &result) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001727 return -1;
1728 if (flags & SO_MASK)
1729 result = -result;
1730#elif defined (M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001731 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001732 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001733 if (d0 != -ENOSYS && entering(tcp)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001734 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001735 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001736 return 0;
1737 }
1738#elif defined (ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001739 /*
1740 * Nothing required
1741 */
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001742#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001743 if (upeek(tcp, PT_R0, &r0) < 0)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001744 return -1;
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001745#elif defined (HPPA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001746 if (upeek(tcp, PT_GR28, &r28) < 0)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001747 return -1;
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001748#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001749 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001750 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001751 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001752 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001753 if (ia32 && r8 != -ENOSYS && entering(tcp)) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001754 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001755 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001756 return 0;
1757 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001758#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001759 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001760 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001761 if (r10 != -ENOSYS && entering(tcp)) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001762 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001763 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001764 return 0;
1765 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001766#elif defined(MICROBLAZE)
1767 if (upeek(tcp, 3 * 4, &r3) < 0)
1768 return -1;
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001769 if (r3 != -ENOSYS && entering(tcp)) {
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001770 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001771 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001772 return 0;
1773 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001774#endif
1775#endif /* LINUX */
Pavel Machek4dc3b142000-02-01 17:58:41 +00001776 return 1;
1777}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001778
Roland McGrathc1e45922008-05-27 23:18:29 +00001779#ifdef LINUX
1780/*
1781 * Check the syscall return value register value for whether it is
1782 * a negated errno code indicating an error, or a success return value.
1783 */
1784static inline int
1785is_negated_errno(unsigned long int val)
1786{
1787 unsigned long int max = -(long int) nerrnos;
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001788# if SUPPORTED_PERSONALITIES > 1
Roland McGrathc1e45922008-05-27 23:18:29 +00001789 if (personality_wordsize[current_personality] < sizeof(val)) {
1790 val = (unsigned int) val;
1791 max = (unsigned int) max;
1792 }
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001793# endif
Roland McGrathc1e45922008-05-27 23:18:29 +00001794 return val > max;
1795}
1796#endif
1797
Roland McGratha4d48532005-06-08 20:45:28 +00001798static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001799get_error(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001800{
1801 int u_error = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001802#ifdef LINUX
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001803 int check_errno = 1;
1804 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
1805 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1806 check_errno = 0;
1807 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001808# if defined(S390) || defined(S390X)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001809 if (check_errno && is_negated_errno(gpr2)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001810 tcp->u_rval = -1;
1811 u_error = -gpr2;
1812 }
1813 else {
1814 tcp->u_rval = gpr2;
1815 u_error = 0;
1816 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001817# elif defined(I386)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001818 if (check_errno && is_negated_errno(eax)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001819 tcp->u_rval = -1;
1820 u_error = -eax;
1821 }
1822 else {
1823 tcp->u_rval = eax;
1824 u_error = 0;
1825 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001826# elif defined(X86_64)
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001827 if (check_errno && is_negated_errno(rax)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001828 tcp->u_rval = -1;
1829 u_error = -rax;
1830 }
1831 else {
1832 tcp->u_rval = rax;
1833 u_error = 0;
1834 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001835# elif defined(IA64)
Roland McGrathc1e45922008-05-27 23:18:29 +00001836 if (ia32) {
1837 int err;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001838
Roland McGrathc1e45922008-05-27 23:18:29 +00001839 err = (int)r8;
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001840 if (check_errno && is_negated_errno(err)) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001841 tcp->u_rval = -1;
1842 u_error = -err;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001843 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001844 else {
1845 tcp->u_rval = err;
1846 u_error = 0;
1847 }
1848 } else {
Dmitry V. Levin50a218d2011-01-18 17:36:20 +00001849 if (check_errno && r10) {
Roland McGrathc1e45922008-05-27 23:18:29 +00001850 tcp->u_rval = -1;
1851 u_error = r8;
1852 } else {
1853 tcp->u_rval = r8;
1854 u_error = 0;
1855 }
1856 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001857# elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001858 if (check_errno && a3) {
1859 tcp->u_rval = -1;
1860 u_error = r2;
1861 } else {
1862 tcp->u_rval = r2;
1863 u_error = 0;
1864 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001865# elif defined(POWERPC)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001866 if (check_errno && is_negated_errno(result)) {
1867 tcp->u_rval = -1;
1868 u_error = -result;
1869 }
1870 else {
1871 tcp->u_rval = result;
1872 u_error = 0;
1873 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001874# elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001875 if (check_errno && is_negated_errno(d0)) {
1876 tcp->u_rval = -1;
1877 u_error = -d0;
1878 }
1879 else {
1880 tcp->u_rval = d0;
1881 u_error = 0;
1882 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001883# elif defined(ARM)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001884 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1885 tcp->u_rval = -1;
1886 u_error = -regs.ARM_r0;
1887 }
1888 else {
1889 tcp->u_rval = regs.ARM_r0;
1890 u_error = 0;
1891 }
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001892# elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001893 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1894 tcp->u_rval = -1;
1895 u_error = -regs.r12;
1896 }
1897 else {
1898 tcp->u_rval = regs.r12;
1899 u_error = 0;
1900 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001901# elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001902 if (check_errno && is_negated_errno(r0)) {
1903 tcp->u_rval = -1;
1904 u_error = -r0;
1905 } else {
1906 tcp->u_rval = r0;
1907 u_error = 0;
1908 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001909# elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001910 if (check_errno && a3) {
1911 tcp->u_rval = -1;
1912 u_error = r0;
1913 }
1914 else {
1915 tcp->u_rval = r0;
1916 u_error = 0;
1917 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001918# elif defined(SPARC)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001919 if (check_errno && regs.psr & PSR_C) {
1920 tcp->u_rval = -1;
1921 u_error = regs.u_regs[U_REG_O0];
1922 }
1923 else {
1924 tcp->u_rval = regs.u_regs[U_REG_O0];
1925 u_error = 0;
1926 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001927# elif defined(SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001928 if (check_errno && regs.tstate & 0x1100000000UL) {
1929 tcp->u_rval = -1;
1930 u_error = regs.u_regs[U_REG_O0];
1931 }
1932 else {
1933 tcp->u_rval = regs.u_regs[U_REG_O0];
1934 u_error = 0;
1935 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001936# elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001937 if (check_errno && is_negated_errno(r28)) {
1938 tcp->u_rval = -1;
1939 u_error = -r28;
1940 }
1941 else {
1942 tcp->u_rval = r28;
1943 u_error = 0;
1944 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001945# elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001946 /* interpret R0 as return value or error number */
1947 if (check_errno && is_negated_errno(r0)) {
1948 tcp->u_rval = -1;
1949 u_error = -r0;
1950 }
1951 else {
1952 tcp->u_rval = r0;
1953 u_error = 0;
1954 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001955# elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001956 /* interpret result as return value or error number */
1957 if (check_errno && is_negated_errno(r9)) {
1958 tcp->u_rval = -1;
1959 u_error = -r9;
1960 }
1961 else {
1962 tcp->u_rval = r9;
1963 u_error = 0;
1964 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001965# elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001966 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1967 tcp->u_rval = -1;
1968 u_error = -r10;
1969 }
1970 else {
1971 tcp->u_rval = r10;
1972 u_error = 0;
1973 }
Chris Metcalfc8c66982009-12-28 10:00:15 -05001974# elif defined(TILE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001975 long rval;
1976 /* interpret result as return value or error number */
1977 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1978 return -1;
1979 if (check_errno && rval < 0 && rval > -nerrnos) {
1980 tcp->u_rval = -1;
1981 u_error = -rval;
1982 }
1983 else {
1984 tcp->u_rval = rval;
1985 u_error = 0;
1986 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001987# elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001988 /* interpret result as return value or error number */
1989 if (check_errno && is_negated_errno(r3)) {
1990 tcp->u_rval = -1;
1991 u_error = -r3;
1992 }
1993 else {
1994 tcp->u_rval = r3;
1995 u_error = 0;
1996 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001997# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001998#endif /* LINUX */
1999#ifdef SUNOS4
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002000 /* get error code from user struct */
2001 if (upeek(tcp, uoff(u_error), &u_error) < 0)
2002 return -1;
2003 u_error >>= 24; /* u_error is a char */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002004
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002005 /* get system call return value */
2006 if (upeek(tcp, uoff(u_rval1), &tcp->u_rval) < 0)
2007 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002008#endif /* SUNOS4 */
2009#ifdef SVR4
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002010# ifdef SPARC
2011 /* Judicious guessing goes a long way. */
2012 if (tcp->status.pr_reg[R_PSR] & 0x100000) {
2013 tcp->u_rval = -1;
2014 u_error = tcp->status.pr_reg[R_O0];
2015 }
2016 else {
2017 tcp->u_rval = tcp->status.pr_reg[R_O0];
2018 u_error = 0;
2019 }
2020# endif /* SPARC */
2021# ifdef I386
2022 /* Wanna know how to kill an hour single-stepping? */
2023 if (tcp->status.PR_REG[EFL] & 0x1) {
2024 tcp->u_rval = -1;
2025 u_error = tcp->status.PR_REG[EAX];
2026 }
2027 else {
2028 tcp->u_rval = tcp->status.PR_REG[EAX];
2029# ifdef HAVE_LONG_LONG
2030 tcp->u_lrval =
2031 ((unsigned long long) tcp->status.PR_REG[EDX] << 32) +
2032 tcp->status.PR_REG[EAX];
2033# endif
2034 u_error = 0;
2035 }
2036# endif /* I386 */
2037# ifdef X86_64
2038 /* Wanna know how to kill an hour single-stepping? */
2039 if (tcp->status.PR_REG[EFLAGS] & 0x1) {
2040 tcp->u_rval = -1;
2041 u_error = tcp->status.PR_REG[RAX];
2042 }
2043 else {
2044 tcp->u_rval = tcp->status.PR_REG[RAX];
2045 u_error = 0;
2046 }
2047# endif /* X86_64 */
2048# ifdef MIPS
2049 if (tcp->status.pr_reg[CTX_A3]) {
2050 tcp->u_rval = -1;
2051 u_error = tcp->status.pr_reg[CTX_V0];
2052 }
2053 else {
2054 tcp->u_rval = tcp->status.pr_reg[CTX_V0];
2055 u_error = 0;
2056 }
2057# endif /* MIPS */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002058#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002059#ifdef FREEBSD
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002060 if (regs.r_eflags & PSL_C) {
2061 tcp->u_rval = -1;
2062 u_error = regs.r_eax;
2063 } else {
2064 tcp->u_rval = regs.r_eax;
2065 tcp->u_lrval =
2066 ((unsigned long long) regs.r_edx << 32) + regs.r_eax;
2067 u_error = 0;
2068 }
Roland McGrath761b5d72002-12-15 23:58:31 +00002069#endif /* FREEBSD */
Pavel Machek4dc3b142000-02-01 17:58:41 +00002070 tcp->u_error = u_error;
2071 return 1;
2072}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002073
Roland McGrathb69f81b2002-12-21 23:25:18 +00002074int
Denys Vlasenko12014262011-05-30 14:00:14 +02002075force_result(struct tcb *tcp, int error, long rval)
Roland McGrathb69f81b2002-12-21 23:25:18 +00002076{
2077#ifdef LINUX
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002078# if defined(S390) || defined(S390X)
Roland McGrathb69f81b2002-12-21 23:25:18 +00002079 gpr2 = error ? -error : rval;
Roland McGrathb69f81b2002-12-21 23:25:18 +00002080 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_GPR2, gpr2) < 0)
2081 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002082# elif defined(I386)
Roland McGrathb69f81b2002-12-21 23:25:18 +00002083 eax = error ? -error : rval;
2084 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(EAX * 4), eax) < 0)
2085 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002086# elif defined(X86_64)
Roland McGrathb69f81b2002-12-21 23:25:18 +00002087 rax = error ? -error : rval;
Roland McGrath998fac72004-06-23 01:40:45 +00002088 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(RAX * 8), rax) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00002089 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002090# elif defined(IA64)
Roland McGrathb69f81b2002-12-21 23:25:18 +00002091 if (ia32) {
2092 r8 = error ? -error : rval;
2093 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0)
2094 return -1;
2095 }
2096 else {
2097 if (error) {
2098 r8 = error;
2099 r10 = -1;
2100 }
2101 else {
2102 r8 = rval;
2103 r10 = 0;
2104 }
2105 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0 ||
2106 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R10), r10) < 0)
2107 return -1;
2108 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002109# elif defined(BFIN)
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00002110 r0 = error ? -error : rval;
2111 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_R0, r0) < 0)
2112 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002113# elif defined(MIPS)
Roland McGrathb69f81b2002-12-21 23:25:18 +00002114 if (error) {
2115 r2 = error;
2116 a3 = -1;
2117 }
2118 else {
2119 r2 = rval;
2120 a3 = 0;
2121 }
Roland McGrath542c2c62008-05-20 01:11:56 +00002122 /* PTRACE_POKEUSER is OK even for n32 since rval is only a long. */
Roland McGrathb69f81b2002-12-21 23:25:18 +00002123 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
2124 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), r2) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002125 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002126# elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002127 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00002128 return -1;
2129 if (error) {
2130 flags |= SO_MASK;
2131 result = error;
2132 }
2133 else {
2134 flags &= ~SO_MASK;
2135 result = rval;
2136 }
Roland McGratheb285352003-01-14 09:59:00 +00002137 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_CCR), flags) < 0 ||
2138 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_R3), result) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00002139 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002140# elif defined(M68K)
Roland McGrathb69f81b2002-12-21 23:25:18 +00002141 d0 = error ? -error : rval;
2142 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_D0), d0) < 0)
2143 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002144# elif defined(ARM)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002145 regs.ARM_r0 = error ? -error : rval;
2146 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*0), regs.ARM_r0) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00002147 return -1;
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002148# elif defined(AVR32)
2149 regs.r12 = error ? -error : rval;
2150 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_R12, regs.r12) < 0)
2151 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002152# elif defined(ALPHA)
Roland McGrathb69f81b2002-12-21 23:25:18 +00002153 if (error) {
2154 a3 = -1;
2155 r0 = error;
2156 }
2157 else {
2158 a3 = 0;
2159 r0 = rval;
2160 }
2161 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
2162 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R0), r0) < 0)
2163 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002164# elif defined(SPARC)
Roland McGrathb69f81b2002-12-21 23:25:18 +00002165 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
2166 return -1;
2167 if (error) {
Mike Frysinger8566c502009-10-12 11:05:14 -04002168 regs.psr |= PSR_C;
2169 regs.u_regs[U_REG_O0] = error;
Roland McGrathb69f81b2002-12-21 23:25:18 +00002170 }
2171 else {
Mike Frysinger8566c502009-10-12 11:05:14 -04002172 regs.psr &= ~PSR_C;
2173 regs.u_regs[U_REG_O0] = rval;
Roland McGrathb69f81b2002-12-21 23:25:18 +00002174 }
2175 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
2176 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002177# elif defined(SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002178 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
2179 return -1;
2180 if (error) {
Mike Frysinger8566c502009-10-12 11:05:14 -04002181 regs.tstate |= 0x1100000000UL;
2182 regs.u_regs[U_REG_O0] = error;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002183 }
2184 else {
Mike Frysinger8566c502009-10-12 11:05:14 -04002185 regs.tstate &= ~0x1100000000UL;
2186 regs.u_regs[U_REG_O0] = rval;
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002187 }
2188 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
2189 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002190# elif defined(HPPA)
Roland McGrathb69f81b2002-12-21 23:25:18 +00002191 r28 = error ? -error : rval;
2192 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR28), r28) < 0)
2193 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002194# elif defined(SH)
Roland McGrathb69f81b2002-12-21 23:25:18 +00002195 r0 = error ? -error : rval;
2196 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*REG_REG0), r0) < 0)
2197 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002198# elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002199 r9 = error ? -error : rval;
Roland McGrathe1e584b2003-06-02 19:18:58 +00002200 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_GENERAL(9), r9) < 0)
2201 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002202# endif
Roland McGrathb69f81b2002-12-21 23:25:18 +00002203#endif /* LINUX */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002204
Roland McGrathb69f81b2002-12-21 23:25:18 +00002205#ifdef SUNOS4
Roland McGratheb9e2e82009-06-02 16:49:22 -07002206 if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_error),
2207 error << 24) < 0 ||
2208 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_rval1), rval) < 0)
Roland McGrathb69f81b2002-12-21 23:25:18 +00002209 return -1;
2210#endif /* SUNOS4 */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002211
Roland McGrathb69f81b2002-12-21 23:25:18 +00002212#ifdef SVR4
2213 /* XXX no clue */
2214 return -1;
2215#endif /* SVR4 */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002216
Roland McGrathb69f81b2002-12-21 23:25:18 +00002217#ifdef FREEBSD
2218 if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002219 perror("pread");
2220 return -1;
2221 }
Roland McGrathb69f81b2002-12-21 23:25:18 +00002222 if (error) {
2223 regs.r_eflags |= PSL_C;
2224 regs.r_eax = error;
2225 }
2226 else {
2227 regs.r_eflags &= ~PSL_C;
2228 regs.r_eax = rval;
2229 }
2230 if (pwrite(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002231 perror("pwrite");
2232 return -1;
2233 }
Roland McGrathb69f81b2002-12-21 23:25:18 +00002234#endif /* FREEBSD */
2235
2236 /* All branches reach here on success (only). */
2237 tcp->u_error = error;
2238 tcp->u_rval = rval;
2239 return 0;
2240}
2241
Roland McGratha4d48532005-06-08 20:45:28 +00002242static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002243syscall_enter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002244{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002245#ifdef LINUX
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002246 int i, nargs;
2247
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002248 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002249 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002250 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002251 nargs = tcp->u_nargs = MAX_ARGS;
2252
2253# if defined(S390) || defined(S390X)
2254 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002255 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
2256 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002257# elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002258 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002259 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
2260 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002261# elif defined(IA64)
2262 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002263 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002264 long rbs_end;
2265 /* be backwards compatible with kernel < 2.4.4... */
2266# ifndef PT_RBS_END
2267# define PT_RBS_END PT_AR_BSP
2268# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00002269
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002270 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
2271 return -1;
2272 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00002273 return -1;
2274
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002275 sof = (cfm >> 0) & 0x7f;
2276 sol = (cfm >> 7) & 0x7f;
2277 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
2278
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002279 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002280 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
2281 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
2282 return -1;
2283 }
2284 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002285 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
2286 PT_R9 /* ECX = out1 */,
2287 PT_R10 /* EDX = out2 */,
2288 PT_R14 /* ESI = out3 */,
2289 PT_R15 /* EDI = out4 */,
2290 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002291
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002292 for (i = 0; i < nargs; ++i) {
2293 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
2294 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002295 /* truncate away IVE sign-extension */
2296 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002297 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002298 }
2299# elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
2300 /* N32 and N64 both use up to six registers. */
2301 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002302
2303 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
2304 return -1;
2305
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002306 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002307 tcp->u_arg[i] = regs[REG_A0 + i];
2308# if defined(LINUX_MIPSN32)
2309 tcp->ext_arg[i] = regs[REG_A0 + i];
2310# endif
2311 }
2312# elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002313 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002314 long sp;
2315
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002316 if (upeek(tcp, REG_SP, &sp) < 0)
2317 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002318 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002319 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
2320 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002321 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002322 (char *)(tcp->u_arg + 4));
2323 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002324 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002325 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002326 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002327 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002328# elif defined(POWERPC)
2329# ifndef PT_ORIG_R3
2330# define PT_ORIG_R3 34
2331# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002332 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002333 if (upeek(tcp, (i==0) ?
2334 (sizeof(unsigned long) * PT_ORIG_R3) :
2335 ((i+PT_R3) * sizeof(unsigned long)),
2336 &tcp->u_arg[i]) < 0)
2337 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002338 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002339# elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002340 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002341 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
2342# elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002343 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002344 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
2345 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002346# elif defined(ARM)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002347 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002348 tcp->u_arg[i] = regs.uregs[i];
2349# elif defined(AVR32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002350 static const unsigned long *argregp[MAX_ARGS] = { &regs.r12,
2351 &regs.r11,
2352 &regs.r10,
2353 &regs.r9,
2354 &regs.r5,
2355 &regs.r3 };
2356 for (i = 0; i < nargs; ++i)
2357 tcp->u_arg[i] = *argregp[i];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002358# elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002359 static const int argreg[MAX_ARGS] = { PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5 };
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002360
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002361 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002362 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
2363 return -1;
2364# elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002365 static const int syscall_regs[MAX_ARGS] = {
2366 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
2367 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002368 };
2369
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002370 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02002371 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002372 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002373# elif defined(SH64)
2374 int i;
2375 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002376 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00002377
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002378 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002379 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
2380 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002381# elif defined(X86_64)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02002382 static const int argreg[SUPPORTED_PERSONALITIES][MAX_ARGS] = {
2383 { 8 * RDI, 8 * RSI, 8 * RDX, 8 * R10, 8 * R8 , 8 * R9 }, /* x86-64 ABI */
2384 { 8 * RBX, 8 * RCX, 8 * RDX, 8 * RSI, 8 * RDI, 8 * RBP } /* i386 ABI */
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002385 };
2386
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002387 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02002388 if (upeek(tcp, argreg[current_personality][i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002389 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002390# elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002391 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002392 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
2393 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002394# elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002395 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002396 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02002397 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002398 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00002399
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002400 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002401 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
2402 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002403# elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002404 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002405 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
2406 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002407# elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002408 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002409 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
2410 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002411# else /* Other architecture (like i386) (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00002412 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002413 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
2414 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002415# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002416#endif /* LINUX */
2417#ifdef SUNOS4
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002418 int i, nargs;
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002419 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002420 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002421 else
Denys Vlasenko4b887a52011-08-23 13:32:38 +02002422 nargs = tcp->u_nargs = MAX_ARGS;
2423 for (i = 0; i < nargs; i++) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002424 struct user *u;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002425
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002426 if (upeek(tcp, uoff(u_arg[0]) +
2427 (i * sizeof(u->u_arg[0])), &tcp->u_arg[i]) < 0)
2428 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002429 }
2430#endif /* SUNOS4 */
2431#ifdef SVR4
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002432# ifdef MIPS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002433 /*
2434 * SGI is broken: even though it has pr_sysarg, it doesn't
2435 * set them on system call entry. Get a clue.
2436 */
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002437 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002438 tcp->u_nargs = sysent[tcp->scno].nargs;
2439 else
2440 tcp->u_nargs = tcp->status.pr_nsysarg;
2441 if (tcp->u_nargs > 4) {
2442 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002443 4 * sizeof(tcp->u_arg[0]));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002444 umoven(tcp, tcp->status.pr_reg[CTX_SP] + 16,
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002445 (tcp->u_nargs - 4) * sizeof(tcp->u_arg[0]), (char *) (tcp->u_arg + 4));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002446 }
2447 else {
2448 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002449 tcp->u_nargs * sizeof(tcp->u_arg[0]));
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002450 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002451# elif UNIXWARE >= 2
John Hughes25299712001-03-06 10:10:06 +00002452 /*
2453 * Like SGI, UnixWare doesn't set pr_sysarg until system call exit
2454 */
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002455 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
John Hughes25299712001-03-06 10:10:06 +00002456 tcp->u_nargs = sysent[tcp->scno].nargs;
2457 else
2458 tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;
2459 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002460 tcp->u_nargs * sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2461# elif defined(HAVE_PR_SYSCALL)
2462 int i;
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002463 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002464 tcp->u_nargs = sysent[tcp->scno].nargs;
2465 else
2466 tcp->u_nargs = tcp->status.pr_nsysarg;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002467 for (i = 0; i < tcp->u_nargs; i++)
2468 tcp->u_arg[i] = tcp->status.pr_sysarg[i];
2469# elif defined(I386)
Denys Vlasenkoafc64032011-08-23 13:29:01 +02002470 if (tcp->scno >= 0 && tcp->scno < nsyscalls)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002471 tcp->u_nargs = sysent[tcp->scno].nargs;
2472 else
2473 tcp->u_nargs = 5;
Denys Vlasenko4660fe62011-06-09 01:32:23 +02002474 if (tcp->u_nargs > 0)
2475 umoven(tcp, tcp->status.PR_REG[UESP] + 4,
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002476 tcp->u_nargs * sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2477# else
John Hughes25299712001-03-06 10:10:06 +00002478 I DONT KNOW WHAT TO DO
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02002479# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002480#endif /* SVR4 */
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002481#ifdef FREEBSD
2482 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2483 sysent[tcp->scno].nargs > tcp->status.val)
2484 tcp->u_nargs = sysent[tcp->scno].nargs;
Roland McGrath761b5d72002-12-15 23:58:31 +00002485 else
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00002486 tcp->u_nargs = tcp->status.val;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002487 if (tcp->u_nargs < 0)
2488 tcp->u_nargs = 0;
2489 if (tcp->u_nargs > MAX_ARGS)
2490 tcp->u_nargs = MAX_ARGS;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002491 switch (regs.r_eax) {
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002492 case SYS___syscall:
2493 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2494 regs.r_esp + sizeof(int) + sizeof(quad_t));
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002495 break;
2496 case SYS_syscall:
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002497 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2498 regs.r_esp + 2 * sizeof(int));
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002499 break;
2500 default:
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002501 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2502 regs.r_esp + sizeof(int));
Denys Vlasenkoadedb512008-12-30 18:47:55 +00002503 break;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002504 }
2505#endif /* FREEBSD */
Pavel Machek4dc3b142000-02-01 17:58:41 +00002506 return 1;
2507}
2508
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002509static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002510trace_syscall_entering(struct tcb *tcp)
2511{
2512 int res, scno_good;
2513
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02002514 scno_good = res = get_scno_on_sysenter(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002515 if (res == 0)
2516 return res;
2517 if (res == 1)
2518 res = syscall_fixup(tcp);
2519 if (res == 0)
2520 return res;
2521 if (res == 1)
2522 res = syscall_enter(tcp);
2523 if (res == 0)
2524 return res;
2525
2526 if (res != 1) {
2527 printleader(tcp);
2528 tcp->flags &= ~TCB_REPRINT;
2529 tcp_last = tcp;
2530 if (scno_good != 1)
2531 tprintf("????" /* anti-trigraph gap */ "(");
2532 else if (tcp->scno >= nsyscalls || tcp->scno < 0)
2533 tprintf("syscall_%lu(", tcp->scno);
2534 else
2535 tprintf("%s(", sysent[tcp->scno].sys_name);
2536 /*
2537 * " <unavailable>" will be added later by the code which
2538 * detects ptrace errors.
2539 */
2540 goto ret;
2541 }
2542
2543 switch (known_scno(tcp)) {
2544#ifdef SYS_socket_subcall
2545 case SYS_socketcall:
2546 decode_subcall(tcp, SYS_socket_subcall,
2547 SYS_socket_nsubcalls, deref_style);
2548 break;
2549#endif
2550#ifdef SYS_ipc_subcall
2551 case SYS_ipc:
2552 decode_subcall(tcp, SYS_ipc_subcall,
2553 SYS_ipc_nsubcalls, shift_style);
2554 break;
2555#endif
2556#ifdef SVR4
2557#ifdef SYS_pgrpsys_subcall
2558 case SYS_pgrpsys:
2559 decode_subcall(tcp, SYS_pgrpsys_subcall,
2560 SYS_pgrpsys_nsubcalls, shift_style);
2561 break;
2562#endif /* SYS_pgrpsys_subcall */
2563#ifdef SYS_sigcall_subcall
2564 case SYS_sigcall:
2565 decode_subcall(tcp, SYS_sigcall_subcall,
2566 SYS_sigcall_nsubcalls, mask_style);
2567 break;
2568#endif /* SYS_sigcall_subcall */
2569 case SYS_msgsys:
2570 decode_subcall(tcp, SYS_msgsys_subcall,
2571 SYS_msgsys_nsubcalls, shift_style);
2572 break;
2573 case SYS_shmsys:
2574 decode_subcall(tcp, SYS_shmsys_subcall,
2575 SYS_shmsys_nsubcalls, shift_style);
2576 break;
2577 case SYS_semsys:
2578 decode_subcall(tcp, SYS_semsys_subcall,
2579 SYS_semsys_nsubcalls, shift_style);
2580 break;
2581 case SYS_sysfs:
2582 decode_subcall(tcp, SYS_sysfs_subcall,
2583 SYS_sysfs_nsubcalls, shift_style);
2584 break;
2585 case SYS_spcall:
2586 decode_subcall(tcp, SYS_spcall_subcall,
2587 SYS_spcall_nsubcalls, shift_style);
2588 break;
2589#ifdef SYS_context_subcall
2590 case SYS_context:
2591 decode_subcall(tcp, SYS_context_subcall,
2592 SYS_context_nsubcalls, shift_style);
2593 break;
2594#endif /* SYS_context_subcall */
2595#ifdef SYS_door_subcall
2596 case SYS_door:
2597 decode_subcall(tcp, SYS_door_subcall,
2598 SYS_door_nsubcalls, door_style);
2599 break;
2600#endif /* SYS_door_subcall */
2601#ifdef SYS_kaio_subcall
2602 case SYS_kaio:
2603 decode_subcall(tcp, SYS_kaio_subcall,
2604 SYS_kaio_nsubcalls, shift_style);
2605 break;
2606#endif
2607#endif /* SVR4 */
2608#ifdef FREEBSD
2609 case SYS_msgsys:
2610 case SYS_shmsys:
2611 case SYS_semsys:
2612 decode_subcall(tcp, 0, 0, table_style);
2613 break;
2614#endif
2615#ifdef SUNOS4
2616 case SYS_semsys:
2617 decode_subcall(tcp, SYS_semsys_subcall,
2618 SYS_semsys_nsubcalls, shift_style);
2619 break;
2620 case SYS_msgsys:
2621 decode_subcall(tcp, SYS_msgsys_subcall,
2622 SYS_msgsys_nsubcalls, shift_style);
2623 break;
2624 case SYS_shmsys:
2625 decode_subcall(tcp, SYS_shmsys_subcall,
2626 SYS_shmsys_nsubcalls, shift_style);
2627 break;
2628#endif
2629 }
2630
2631 internal_syscall(tcp);
2632
2633 if ((tcp->scno >= 0 && tcp->scno < nsyscalls &&
2634 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
2635 (tracing_paths && !pathtrace_match(tcp))) {
2636 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
2637 return 0;
2638 }
2639
2640 tcp->flags &= ~TCB_FILTERED;
2641
2642 if (cflag == CFLAG_ONLY_STATS) {
2643 res = 0;
2644 goto ret;
2645 }
2646
2647 printleader(tcp);
2648 tcp->flags &= ~TCB_REPRINT;
2649 tcp_last = tcp;
2650 if (tcp->scno >= nsyscalls || tcp->scno < 0)
2651 tprintf("syscall_%lu(", tcp->scno);
2652 else
2653 tprintf("%s(", sysent[tcp->scno].sys_name);
2654 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2655 ((qual_flags[tcp->scno] & QUAL_RAW) &&
2656 sysent[tcp->scno].sys_func != sys_exit))
2657 res = printargs(tcp);
2658 else
2659 res = (*sysent[tcp->scno].sys_func)(tcp);
2660
2661 if (fflush(tcp->outf) == EOF)
2662 return -1;
2663 ret:
2664 tcp->flags |= TCB_INSYSCALL;
2665 /* Measure the entrance time as late as possible to avoid errors. */
2666 if (dtime || cflag)
2667 gettimeofday(&tcp->etime, NULL);
2668 return res;
2669}
2670
2671static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002672trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002673{
2674 int sys_res;
2675 struct timeval tv;
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002676 int res, scno_good;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002677 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002678
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002679 /* Measure the exit time as early as possible to avoid errors. */
2680 if (dtime || cflag)
2681 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002682
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002683 /* BTW, why we don't just memorize syscall no. on entry
2684 * in tcp->something?
2685 */
Denys Vlasenko9a36ae52011-08-24 16:47:32 +02002686 scno_good = res = get_scno_on_sysexit(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002687 if (res == 0)
2688 return res;
2689 if (res == 1)
2690 res = syscall_fixup(tcp);
2691 if (res == 0)
2692 return res;
2693 if (res == 1)
2694 res = get_error(tcp);
2695 if (res == 0)
2696 return res;
2697 if (res == 1)
2698 internal_syscall(tcp);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00002699
Grant Edwards8a082772011-04-07 20:25:40 +00002700 if (res == 1 && filtered(tcp)) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002701 goto ret;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002702 }
2703
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002704 if (tcp->flags & TCB_REPRINT) {
2705 printleader(tcp);
2706 tprintf("<... ");
2707 if (scno_good != 1)
2708 tprintf("????");
2709 else if (tcp->scno >= nsyscalls || tcp->scno < 0)
2710 tprintf("syscall_%lu", tcp->scno);
2711 else
2712 tprintf("%s", sysent[tcp->scno].sys_name);
2713 tprintf(" resumed> ");
2714 }
2715
2716 if (cflag) {
2717 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002718 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002719 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002720 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002721 }
2722 }
2723
2724 if (res != 1) {
2725 tprintf(") ");
2726 tabto(acolumn);
2727 tprintf("= ? <unavailable>");
2728 printtrailer();
2729 tcp->flags &= ~TCB_INSYSCALL;
2730 return res;
2731 }
2732
2733 if (tcp->scno >= nsyscalls || tcp->scno < 0
2734 || (qual_flags[tcp->scno] & QUAL_RAW))
2735 sys_res = printargs(tcp);
2736 else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002737 /* FIXME: not_failing_only (IOW, option -z) is broken:
2738 * failure of syscall is known only after syscall return.
2739 * Thus we end up with something like this on, say, ENOENT:
2740 * open("doesnt_exist", O_RDONLY <unfinished ...>
2741 * {next syscall decode}
2742 * whereas the intended result is that open(...) line
2743 * is not shown at all.
2744 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002745 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002746 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002747 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2748 }
2749
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002750 tprintf(") ");
2751 tabto(acolumn);
Denys Vlasenko3b738812011-08-22 02:06:35 +02002752 u_error = tcp->u_error;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002753 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2754 qual_flags[tcp->scno] & QUAL_RAW) {
2755 if (u_error)
2756 tprintf("= -1 (errno %ld)", u_error);
2757 else
2758 tprintf("= %#lx", tcp->u_rval);
2759 }
2760 else if (!(sys_res & RVAL_NONE) && u_error) {
2761 switch (u_error) {
2762#ifdef LINUX
2763 case ERESTARTSYS:
2764 tprintf("= ? ERESTARTSYS (To be restarted)");
2765 break;
2766 case ERESTARTNOINTR:
2767 tprintf("= ? ERESTARTNOINTR (To be restarted)");
2768 break;
2769 case ERESTARTNOHAND:
2770 tprintf("= ? ERESTARTNOHAND (To be restarted)");
2771 break;
2772 case ERESTART_RESTARTBLOCK:
2773 tprintf("= ? ERESTART_RESTARTBLOCK (To be restarted)");
2774 break;
2775#endif /* LINUX */
2776 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002777 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002778 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002779 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002780 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002781 strerror(u_error));
2782 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002783 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002784 strerror(u_error));
2785 break;
2786 }
2787 if ((sys_res & RVAL_STR) && tcp->auxstr)
2788 tprintf(" (%s)", tcp->auxstr);
2789 }
2790 else {
2791 if (sys_res & RVAL_NONE)
2792 tprintf("= ?");
2793 else {
2794 switch (sys_res & RVAL_MASK) {
2795 case RVAL_HEX:
2796 tprintf("= %#lx", tcp->u_rval);
2797 break;
2798 case RVAL_OCTAL:
2799 tprintf("= %#lo", tcp->u_rval);
2800 break;
2801 case RVAL_UDECIMAL:
2802 tprintf("= %lu", tcp->u_rval);
2803 break;
2804 case RVAL_DECIMAL:
2805 tprintf("= %ld", tcp->u_rval);
2806 break;
2807#ifdef HAVE_LONG_LONG
2808 case RVAL_LHEX:
2809 tprintf("= %#llx", tcp->u_lrval);
2810 break;
2811 case RVAL_LOCTAL:
2812 tprintf("= %#llo", tcp->u_lrval);
2813 break;
2814 case RVAL_LUDECIMAL:
2815 tprintf("= %llu", tcp->u_lrval);
2816 break;
2817 case RVAL_LDECIMAL:
2818 tprintf("= %lld", tcp->u_lrval);
2819 break;
2820#endif
2821 default:
2822 fprintf(stderr,
2823 "invalid rval format\n");
2824 break;
2825 }
2826 }
2827 if ((sys_res & RVAL_STR) && tcp->auxstr)
2828 tprintf(" (%s)", tcp->auxstr);
2829 }
2830 if (dtime) {
2831 tv_sub(&tv, &tv, &tcp->etime);
2832 tprintf(" <%ld.%06ld>",
2833 (long) tv.tv_sec, (long) tv.tv_usec);
2834 }
2835 printtrailer();
2836
2837 dumpio(tcp);
2838 if (fflush(tcp->outf) == EOF)
2839 return -1;
Denys Vlasenko3b738812011-08-22 02:06:35 +02002840 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002841 tcp->flags &= ~TCB_INSYSCALL;
2842 return 0;
2843}
2844
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002845int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002846trace_syscall(struct tcb *tcp)
2847{
2848 return exiting(tcp) ?
2849 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2850}
2851
2852int
Denys Vlasenko12014262011-05-30 14:00:14 +02002853printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002854{
2855 if (entering(tcp)) {
2856 int i;
2857
2858 for (i = 0; i < tcp->u_nargs; i++)
2859 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
2860 }
2861 return 0;
2862}
2863
2864long
Denys Vlasenko12014262011-05-30 14:00:14 +02002865getrval2(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002866{
2867 long val = -1;
2868
2869#ifdef LINUX
Roland McGrath6d1a65c2004-07-12 07:44:08 +00002870#if defined (SPARC) || defined (SPARC64)
Mike Frysinger8566c502009-10-12 11:05:14 -04002871 struct pt_regs regs;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02002872 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002873 return -1;
Mike Frysinger8566c502009-10-12 11:05:14 -04002874 val = regs.u_regs[U_REG_O1];
Roland McGrath6b1d43e2003-03-31 01:05:01 +00002875#elif defined(SH)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002876 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
Roland McGrath6b1d43e2003-03-31 01:05:01 +00002877 return -1;
Roland McGrathb4ce1762004-03-01 20:30:48 +00002878#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002879 if (upeek(tcp, PT_R9, &val) < 0)
Roland McGrathb4ce1762004-03-01 20:30:48 +00002880 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002881#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002882#endif /* LINUX */
2883
2884#ifdef SUNOS4
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00002885 if (upeek(tcp, uoff(u_rval2), &val) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002886 return -1;
2887#endif /* SUNOS4 */
2888
2889#ifdef SVR4
2890#ifdef SPARC
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002891 val = tcp->status.PR_REG[R_O1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002892#endif /* SPARC */
2893#ifdef I386
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002894 val = tcp->status.PR_REG[EDX];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002895#endif /* I386 */
Michal Ludvig0e035502002-09-23 15:41:01 +00002896#ifdef X86_64
2897 val = tcp->status.PR_REG[RDX];
2898#endif /* X86_64 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002899#ifdef MIPS
Wichert Akkerman9ce1a631999-08-29 23:15:07 +00002900 val = tcp->status.PR_REG[CTX_V1];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002901#endif /* MIPS */
2902#endif /* SVR4 */
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00002903
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +00002904#ifdef FREEBSD
2905 struct reg regs;
2906 pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
2907 val = regs.r_edx;
Roland McGrath761b5d72002-12-15 23:58:31 +00002908#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002909 return val;
2910}
2911
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +00002912#ifdef SUNOS4
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002913/*
2914 * Apparently, indirect system calls have already be converted by ptrace(2),
2915 * so if you see "indir" this program has gone astray.
2916 */
2917int
Denys Vlasenko12014262011-05-30 14:00:14 +02002918sys_indir(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002919{
2920 int i, scno, nargs;
2921
2922 if (entering(tcp)) {
Denys Vlasenko5d645812011-08-20 12:48:18 +02002923 scno = tcp->u_arg[0];
2924 if (scno > nsyscalls) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002925 fprintf(stderr, "Bogus syscall: %u\n", scno);
2926 return 0;
2927 }
2928 nargs = sysent[scno].nargs;
2929 tprintf("%s", sysent[scno].sys_name);
2930 for (i = 0; i < nargs; i++)
2931 tprintf(", %#lx", tcp->u_arg[i+1]);
2932 }
2933 return 0;
2934}
Dmitry V. Levinb9fe0112006-12-13 16:59:44 +00002935#endif /* SUNOS4 */
Dmitry V. Levin2e55ff42008-09-03 01:02:46 +00002936
2937int
2938is_restart_error(struct tcb *tcp)
2939{
2940#ifdef LINUX
2941 if (!syserror(tcp))
2942 return 0;
2943 switch (tcp->u_error) {
2944 case ERESTARTSYS:
2945 case ERESTARTNOINTR:
2946 case ERESTARTNOHAND:
2947 case ERESTART_RESTARTBLOCK:
2948 return 1;
2949 default:
2950 break;
2951 }
2952#endif /* LINUX */
2953 return 0;
2954}