blob: b94ad6516cf7bb9ff57d9f42c047337fa20762ab [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
Denys Vlasenko84703742012-02-25 02:38:52 +010063#if 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
Denys Vlasenko84703742012-02-25 02:38:52 +010068#endif
Roland McGrath6d1a65c2004-07-12 07:44:08 +000069
Denys Vlasenko84703742012-02-25 02:38:52 +010070#if defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000071# include <asm/ptrace_offsets.h>
72# include <asm/rse.h>
73#endif
74
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000075#ifndef ERESTARTSYS
76#define ERESTARTSYS 512
77#endif
78#ifndef ERESTARTNOINTR
79#define ERESTARTNOINTR 513
80#endif
81#ifndef ERESTARTNOHAND
82#define ERESTARTNOHAND 514 /* restart if no handler.. */
83#endif
84#ifndef ENOIOCTLCMD
85#define ENOIOCTLCMD 515 /* No ioctl command */
86#endif
Roland McGrath9c555e72003-07-09 09:47:59 +000087#ifndef ERESTART_RESTARTBLOCK
88#define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
89#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000090#ifndef NSIG
Denys Vlasenko041b3ee2011-08-18 12:48:56 +020091#warning: NSIG is not defined, using 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000092#define NSIG 32
93#endif
94#ifdef ARM
Denys Vlasenko041b3ee2011-08-18 12:48:56 +020095/* Ugh. Is this really correct? ARM has no RT signals?! */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000096#undef NSIG
97#define NSIG 32
98#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000099
100#include "syscall.h"
101
102/* Define these shorthand notations to simplify the syscallent files. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000103#define TD TRACE_DESC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000104#define TF TRACE_FILE
105#define TI TRACE_IPC
106#define TN TRACE_NETWORK
107#define TP TRACE_PROCESS
108#define TS TRACE_SIGNAL
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000109#define NF SYSCALL_NEVER_FAILS
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200110#define MA MAX_ARGS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000111
Roland McGrathee36ce12004-09-04 03:53:10 +0000112static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000113#include "syscallent.h"
114};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000115
116#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000117static const struct sysent sysent1[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118#include "syscallent1.h"
119};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200120#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121
122#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000123static const struct sysent sysent2[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000124#include "syscallent2.h"
125};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200126#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000127
128/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000129#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130#undef TF
131#undef TI
132#undef TN
133#undef TP
134#undef TS
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000135#undef NF
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200136#undef MA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000137
Denys Vlasenko39fca622011-08-20 02:12:33 +0200138
139/*
140 * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
141 * program `ioctlsort', such that the list is sorted by the `code' field.
142 * This has the side-effect of resolving the _IO.. macros into
143 * plain integers, eliminating the need to include here everything
144 * in "/usr/include".
145 */
146
147
Roland McGrathee36ce12004-09-04 03:53:10 +0000148static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000149#include "errnoent.h"
150};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200151static const char *const signalent0[] = {
152#include "signalent.h"
153};
154static const struct ioctlent ioctlent0[] = {
155#include "ioctlent.h"
156};
157enum { nsyscalls0 = ARRAY_SIZE(sysent0) };
158enum { nerrnos0 = ARRAY_SIZE(errnoent0) };
159enum { nsignals0 = ARRAY_SIZE(signalent0) };
160enum { nioctlents0 = ARRAY_SIZE(ioctlent0) };
161int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000162
163#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000164static const char *const errnoent1[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000165#include "errnoent1.h"
166};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200167static const char *const signalent1[] = {
168#include "signalent1.h"
169};
170static const struct ioctlent ioctlent1[] = {
171#include "ioctlent1.h"
172};
173enum { nsyscalls1 = ARRAY_SIZE(sysent1) };
174enum { nerrnos1 = ARRAY_SIZE(errnoent1) };
175enum { nsignals1 = ARRAY_SIZE(signalent1) };
176enum { nioctlents1 = ARRAY_SIZE(ioctlent1) };
177int qual_flags1[MAX_QUALS];
178#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000179
180#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000181static const char *const errnoent2[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000182#include "errnoent2.h"
183};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200184static const char *const signalent2[] = {
185#include "signalent2.h"
186};
187static const struct ioctlent ioctlent2[] = {
188#include "ioctlent2.h"
189};
190enum { nsyscalls2 = ARRAY_SIZE(sysent2) };
191enum { nerrnos2 = ARRAY_SIZE(errnoent2) };
192enum { nsignals2 = ARRAY_SIZE(signalent2) };
193enum { nioctlents2 = ARRAY_SIZE(ioctlent2) };
194int qual_flags2[MAX_QUALS];
195#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000196
Denys Vlasenko39fca622011-08-20 02:12:33 +0200197
198const struct sysent *sysent;
Roland McGrathee36ce12004-09-04 03:53:10 +0000199const char *const *errnoent;
Denys Vlasenko39fca622011-08-20 02:12:33 +0200200const char *const *signalent;
201const struct ioctlent *ioctlent;
Denys Vlasenkoafc64032011-08-23 13:29:01 +0200202unsigned nsyscalls;
203unsigned nerrnos;
204unsigned nsignals;
205unsigned nioctlents;
Denys Vlasenko39fca622011-08-20 02:12:33 +0200206int *qual_flags;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000207
208int current_personality;
209
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000210#ifndef PERSONALITY0_WORDSIZE
211# define PERSONALITY0_WORDSIZE sizeof(long)
212#endif
213const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
214 PERSONALITY0_WORDSIZE,
215#if SUPPORTED_PERSONALITIES > 1
216 PERSONALITY1_WORDSIZE,
217#endif
218#if SUPPORTED_PERSONALITIES > 2
219 PERSONALITY2_WORDSIZE,
220#endif
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200221};
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000222
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200223void
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000224set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000225{
226 switch (personality) {
227 case 0:
228 errnoent = errnoent0;
229 nerrnos = nerrnos0;
230 sysent = sysent0;
231 nsyscalls = nsyscalls0;
232 ioctlent = ioctlent0;
233 nioctlents = nioctlents0;
234 signalent = signalent0;
235 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000236 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000237 break;
238
239#if SUPPORTED_PERSONALITIES >= 2
240 case 1:
241 errnoent = errnoent1;
242 nerrnos = nerrnos1;
243 sysent = sysent1;
244 nsyscalls = nsyscalls1;
245 ioctlent = ioctlent1;
246 nioctlents = nioctlents1;
247 signalent = signalent1;
248 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000249 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000250 break;
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200251#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000252
253#if SUPPORTED_PERSONALITIES >= 3
254 case 2:
255 errnoent = errnoent2;
256 nerrnos = nerrnos2;
257 sysent = sysent2;
258 nsyscalls = nsyscalls2;
259 ioctlent = ioctlent2;
260 nioctlents = nioctlents2;
261 signalent = signalent2;
262 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000263 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000264 break;
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200265#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000266 }
267
268 current_personality = personality;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000269}
270
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000271#if SUPPORTED_PERSONALITIES > 1
272static void
273update_personality(struct tcb *tcp, int personality)
274{
275 if (personality == current_personality)
276 return;
277 set_personality(personality);
278
279 if (personality == tcp->currpers)
280 return;
281 tcp->currpers = personality;
282
283#if defined(POWERPC64) || defined(X86_64)
284 if (!qflag) {
285 static const char *const names[] = {"64 bit", "32 bit"};
286 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
287 tcp->pid, names[personality]);
288 }
289#endif
290}
291#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000292
Roland McGrath9797ceb2002-12-30 10:23:00 +0000293static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000294
Roland McGrathe10e62a2004-09-04 04:20:43 +0000295static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000296 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000297 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000298 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000299 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000300} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000301 { QUAL_TRACE, "trace", qual_syscall, "system call" },
302 { QUAL_TRACE, "t", qual_syscall, "system call" },
303 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
304 { QUAL_ABBREV, "a", qual_syscall, "system call" },
305 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
306 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
307 { QUAL_RAW, "raw", qual_syscall, "system call" },
308 { QUAL_RAW, "x", qual_syscall, "system call" },
309 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
310 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
311 { QUAL_SIGNAL, "s", qual_signal, "signal" },
312 { QUAL_FAULT, "fault", qual_fault, "fault" },
313 { QUAL_FAULT, "faults", qual_fault, "fault" },
314 { QUAL_FAULT, "m", qual_fault, "fault" },
315 { QUAL_READ, "read", qual_desc, "descriptor" },
316 { QUAL_READ, "reads", qual_desc, "descriptor" },
317 { QUAL_READ, "r", qual_desc, "descriptor" },
318 { QUAL_WRITE, "write", qual_desc, "descriptor" },
319 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
320 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000321 { 0, NULL, NULL, NULL },
322};
323
Roland McGrath9797ceb2002-12-30 10:23:00 +0000324static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000325qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000326{
Roland McGrath138c6a32006-01-12 09:50:49 +0000327 if (pers == 0 || pers < 0) {
328 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000329 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000330 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000331 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000332 }
333
334#if SUPPORTED_PERSONALITIES >= 2
335 if (pers == 1 || pers < 0) {
336 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000337 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000338 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000339 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000340 }
341#endif /* SUPPORTED_PERSONALITIES >= 2 */
342
343#if SUPPORTED_PERSONALITIES >= 3
344 if (pers == 2 || pers < 0) {
345 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000346 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000347 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000348 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000349 }
350#endif /* SUPPORTED_PERSONALITIES >= 3 */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000351}
352
353static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000354qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000355{
356 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000357 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000358
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000359 if (isdigit((unsigned char)*s)) {
360 int i = atoi(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000361 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000362 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000363 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000364 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000365 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000366 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000367 if (strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000368 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000369 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000370 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000371
372#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000373 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000374 if (strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000375 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000376 rc = 0;
377 }
378#endif /* SUPPORTED_PERSONALITIES >= 2 */
379
380#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000381 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000382 if (strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000383 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000384 rc = 0;
385 }
386#endif /* SUPPORTED_PERSONALITIES >= 3 */
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000387
Roland McGrathfe6b3522005-02-02 04:40:11 +0000388 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000389}
390
391static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000392qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000393{
394 int i;
395 char buf[32];
396
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000397 if (isdigit((unsigned char)*s)) {
398 int signo = atoi(s);
399 if (signo < 0 || signo >= MAX_QUALS)
400 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000401 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000402 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000403 }
Roland McGrathd62b6712004-03-02 06:52:01 +0000404 if (strlen(s) >= sizeof buf)
Roland McGrathfe6b3522005-02-02 04:40:11 +0000405 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000406 strcpy(buf, s);
407 s = buf;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000408 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000409 s += 3;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000410 for (i = 0; i <= NSIG; i++)
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000411 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000412 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000413 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000414 }
Roland McGrath76421df2005-02-02 03:51:18 +0000415 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000416}
417
418static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000419qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000420{
421 return -1;
422}
423
424static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000425qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000426{
Roland McGrath48a035f2006-01-12 09:45:56 +0000427 if (isdigit((unsigned char)*s)) {
Roland McGrathfe6b3522005-02-02 04:40:11 +0000428 int desc = atoi(s);
429 if (desc < 0 || desc >= MAX_QUALS)
430 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000431 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000432 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000433 }
434 return -1;
435}
436
437static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000438lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000439{
440 if (strcmp(s, "file") == 0)
441 return TRACE_FILE;
442 if (strcmp(s, "ipc") == 0)
443 return TRACE_IPC;
444 if (strcmp(s, "network") == 0)
445 return TRACE_NETWORK;
446 if (strcmp(s, "process") == 0)
447 return TRACE_PROCESS;
448 if (strcmp(s, "signal") == 0)
449 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000450 if (strcmp(s, "desc") == 0)
451 return TRACE_DESC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000452 return -1;
453}
454
455void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000456qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000457{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000458 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000459 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000460 char *copy;
461 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000462 int i, n;
463
464 opt = &qual_options[0];
465 for (i = 0; (p = qual_options[i].option_name); i++) {
466 n = strlen(p);
467 if (strncmp(s, p, n) == 0 && s[n] == '=') {
468 opt = &qual_options[i];
469 s += n + 1;
470 break;
471 }
472 }
473 not = 0;
474 if (*s == '!') {
475 not = 1;
476 s++;
477 }
478 if (strcmp(s, "none") == 0) {
479 not = 1 - not;
480 s = "all";
481 }
482 if (strcmp(s, "all") == 0) {
483 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000484 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000485 }
486 return;
487 }
488 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000489 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000490 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200491 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200492 if (!copy)
493 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000494 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000495 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000496 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000497 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000498 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000499
500#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000501 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000502 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000503 qualify_one(i, opt->bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000504#endif /* SUPPORTED_PERSONALITIES >= 2 */
505
506#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000507 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000508 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000509 qualify_one(i, opt->bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000510#endif /* SUPPORTED_PERSONALITIES >= 3 */
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000511
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000512 continue;
513 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000514 if (opt->qualify(p, opt->bitflag, not)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000515 fprintf(stderr, "strace: invalid %s `%s'\n",
516 opt->argument_name, p);
517 exit(1);
518 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000519 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000520 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000521 return;
522}
523
Wichert Akkerman8829a551999-06-11 13:18:40 +0000524enum subcall_style { shift_style, deref_style, mask_style, door_style };
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000525
Denys Vlasenko84703742012-02-25 02:38:52 +0100526#if !(defined(ALPHA) || defined(MIPS) || defined(__ARM_EABI__))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000527
Roland McGratha4d48532005-06-08 20:45:28 +0000528static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200529decode_subcall(struct tcb *tcp, int subcall, int nsubcalls, enum subcall_style style)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000530{
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000531 unsigned long addr, mask;
Denys Vlasenko4b887a52011-08-23 13:32:38 +0200532 int i, n;
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000533 int size = personality_wordsize[current_personality];
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000534
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000535 switch (style) {
536 case shift_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000537 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
538 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000539 tcp->scno = subcall + tcp->u_arg[0];
Denys Vlasenko4b887a52011-08-23 13:32:38 +0200540 tcp->u_nargs = n = sysent[tcp->scno].nargs;
541 for (i = 0; i < n; i++)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000542 tcp->u_arg[i] = tcp->u_arg[i + 1];
543 break;
544 case deref_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000545 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
546 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000547 tcp->scno = subcall + tcp->u_arg[0];
548 addr = tcp->u_arg[1];
Denys Vlasenko4b887a52011-08-23 13:32:38 +0200549 tcp->u_nargs = n = sysent[tcp->scno].nargs;
550 for (i = 0; i < n; i++) {
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000551 if (size == sizeof(int)) {
552 unsigned int arg;
553 if (umove(tcp, addr, &arg) < 0)
554 arg = 0;
555 tcp->u_arg[i] = arg;
556 }
557 else if (size == sizeof(long)) {
558 unsigned long arg;
559 if (umove(tcp, addr, &arg) < 0)
560 arg = 0;
561 tcp->u_arg[i] = arg;
562 }
563 else
564 abort();
565 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000566 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000567 break;
568 case mask_style:
569 mask = (tcp->u_arg[0] >> 8) & 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000570 for (i = 0; mask; i++)
571 mask >>= 1;
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000572 if (i >= nsubcalls)
573 return;
574 tcp->u_arg[0] &= 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000575 tcp->scno = subcall + i;
Denys Vlasenkoafc64032011-08-23 13:29:01 +0200576 tcp->u_nargs = sysent[tcp->scno].nargs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000577 break;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000578 case door_style:
579 /*
580 * Oh, yuck. The call code is the *sixth* argument.
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000581 * (don't you mean the *last* argument? - JH)
Wichert Akkerman8829a551999-06-11 13:18:40 +0000582 */
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000583 if (tcp->u_arg[5] < 0 || tcp->u_arg[5] >= nsubcalls)
584 return;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000585 tcp->scno = subcall + tcp->u_arg[5];
Denys Vlasenkoafc64032011-08-23 13:29:01 +0200586 tcp->u_nargs = sysent[tcp->scno].nargs;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000587 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000588 }
589}
590#endif
591
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200592int
593printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000594{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200595 if (entering(tcp)) {
596 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000597
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200598 for (i = 0; i < tcp->u_nargs; i++)
599 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
600 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000601 return 0;
602}
603
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200604long
605getrval2(struct tcb *tcp)
606{
607 long val = -1;
608
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200609#if defined (SPARC) || defined (SPARC64)
610 struct pt_regs regs;
611 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
612 return -1;
613 val = regs.u_regs[U_REG_O1];
614#elif defined(SH)
615 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
616 return -1;
617#elif defined(IA64)
618 if (upeek(tcp, PT_R9, &val) < 0)
619 return -1;
620#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200621
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200622
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200623
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200624 return val;
625}
626
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200627
628int
629is_restart_error(struct tcb *tcp)
630{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200631 switch (tcp->u_error) {
632 case ERESTARTSYS:
633 case ERESTARTNOINTR:
634 case ERESTARTNOHAND:
635 case ERESTART_RESTARTBLOCK:
636 return 1;
637 default:
638 break;
639 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200640 return 0;
641}
642
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100643# if defined(I386)
644struct pt_regs i386_regs;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200645# elif defined(X86_64)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100646/*
647 * On 32 bits, pt_regs and user_regs_struct are the same,
648 * but on 64 bits, user_regs_struct has six more fields:
649 * fs_base, gs_base, ds, es, fs, gs.
650 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
651 */
652static struct user_regs_struct x86_64_regs;
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200653# elif defined (IA64)
654long r8, r10, psr; /* TODO: make static? */
655long ia32 = 0; /* not static */
656# elif defined (POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +0200657static long result;
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200658# elif defined (M68K)
659static long d0;
660# elif defined(BFIN)
661static long r0;
662# elif defined (ARM)
663static struct pt_regs regs;
664# elif defined (ALPHA)
665static long r0;
666static long a3;
667# elif defined(AVR32)
668static struct pt_regs regs;
669# elif defined (SPARC) || defined (SPARC64)
670static struct pt_regs regs;
671static unsigned long trap;
672# elif defined(LINUX_MIPSN32)
673static long long a3;
674static long long r2;
675# elif defined(MIPS)
676static long a3;
677static long r2;
678# elif defined(S390) || defined(S390X)
679static long gpr2;
680static long pc;
681static long syscall_mode;
682# elif defined(HPPA)
683static long r28;
684# elif defined(SH)
685static long r0;
686# elif defined(SH64)
687static long r9;
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200688# elif defined(CRISV10) || defined(CRISV32)
689static long r10;
690# elif defined(MICROBLAZE)
691static long r3;
692# endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000693
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200694/* Returns:
695 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
696 * 1: ok, continue in trace_syscall().
697 * other: error, trace_syscall() should print error indicator
698 * ("????" etc) and bail out.
699 */
Denys Vlasenko9a36ae52011-08-24 16:47:32 +0200700static
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000701int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200702get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000703{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000704 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000705
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000706# if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000707 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200708 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000709
710 if (syscall_mode != -ENOSYS) {
711 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000712 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000713 */
714 scno = syscall_mode;
715 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000716 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000717 * Old style of "passing" the scno via the SVC instruction.
718 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000719 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200720 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200721 static const int gpr_offset[16] = {
722 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
723 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
724 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
725 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
726 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000727
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000728 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000729 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000730 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000731 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000732 if (errno) {
733 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000734 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000735 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000736
737 /*
738 * We have to check if the SVC got executed directly or via an
739 * EXECUTE instruction. In case of EXECUTE it is necessary to do
740 * instruction decoding to derive the system call number.
741 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
742 * so that this doesn't work if a SVC opcode is part of an EXECUTE
743 * opcode. Since there is no way to find out the opcode size this
744 * is the best we can do...
745 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000746 if ((opcode & 0xff00) == 0x0a00) {
747 /* SVC opcode */
748 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000749 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000750 else {
751 /* SVC got executed by EXECUTE instruction */
752
753 /*
754 * Do instruction decoding of EXECUTE. If you really want to
755 * understand this, read the Principles of Operations.
756 */
757 svc_addr = (void *) (opcode & 0xfff);
758
759 tmp = 0;
760 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000761 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000762 return -1;
763 svc_addr += tmp;
764
765 tmp = 0;
766 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000767 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000768 return -1;
769 svc_addr += tmp;
770
Denys Vlasenkofb036672009-01-23 16:30:26 +0000771 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000772 if (errno)
773 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000774# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000775 scno >>= 48;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000776# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000777 scno >>= 16;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000778# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000779 tmp = 0;
780 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000781 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000782 return -1;
783
784 scno = (scno | tmp) & 0xff;
785 }
786 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000787# elif defined (POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000788 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000789 return -1;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200790# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200791 /* TODO: speed up strace by not doing this at every syscall.
792 * We only need to do it after execve.
793 */
794 int currpers;
795 long val;
796 int pid = tcp->pid;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200797
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200798 /* Check for 64/32 bit mode. */
799 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
800 return -1;
801 /* SF is bit 0 of MSR */
802 if (val < 0)
803 currpers = 0;
804 else
805 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000806 update_personality(tcp, currpers);
Andreas Schwabd69fa492010-07-12 21:39:57 +0200807# endif
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000808# elif defined(AVR32)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200809 /* Read complete register set in one go. */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000810 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
811 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200812 scno = regs.r8;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000813# elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000814 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000815 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000816# elif defined (I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200817 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000818 return -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200819 scno = i386_regs.orig_eax;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000820# elif defined (X86_64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200821 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200822 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
823 return -1;
824 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +0000825
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200826 /* Check CS register value. On x86-64 linux it is:
827 * 0x33 for long mode (64 bit)
828 * 0x23 for compatibility mode (32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200829 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200830 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200831 case 0x23: currpers = 1; break;
832 case 0x33: currpers = 0; break;
833 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200834 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200835 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200836 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200837 currpers = current_personality;
838 break;
839 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000840# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200841 /* This version analyzes the opcode of a syscall instruction.
842 * (int 0x80 on i386 vs. syscall on x86-64)
843 * It works, but is too complicated.
844 */
845 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +0000846
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200847 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +0000848
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200849 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
850 rip -= 2;
851 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +0000852
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200853 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200854 if (errno)
855 fprintf(stderr, "ptrace_peektext failed: %s\n",
856 strerror(errno));
857 switch (call & 0xffff) {
858 /* x86-64: syscall = 0x0f 0x05 */
859 case 0x050f: currpers = 0; break;
860 /* i386: int 0x80 = 0xcd 0x80 */
861 case 0x80cd: currpers = 1; break;
862 default:
863 currpers = current_personality;
864 fprintf(stderr,
865 "Unknown syscall opcode (0x%04X) while "
866 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200867 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200868 break;
869 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000870# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000871 update_personality(tcp, currpers);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000872# elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000873# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200874 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000875 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200876 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200877 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200878 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000879 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200880 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000881 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200882 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000883# elif defined (ARM)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200884 /* Read complete register set in one go. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000885 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +0000886 return -1;
887
888 /*
889 * We only need to grab the syscall number on syscall entry.
890 */
891 if (regs.ARM_ip == 0) {
892 /*
893 * Note: we only deal with only 32-bit CPUs here.
894 */
895 if (regs.ARM_cpsr & 0x20) {
896 /*
897 * Get the Thumb-mode system call number
898 */
899 scno = regs.ARM_r7;
900 } else {
901 /*
902 * Get the ARM-mode system call number
903 */
904 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000905 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +0000906 if (errno)
907 return -1;
908
Roland McGrathf691bd22006-04-25 07:34:41 +0000909 /* Handle the EABI syscall convention. We do not
910 bother converting structures between the two
911 ABIs, but basic functionality should work even
912 if strace and the traced program have different
913 ABIs. */
914 if (scno == 0xef000000) {
915 scno = regs.ARM_r7;
916 } else {
917 if ((scno & 0x0ff00000) != 0x0f900000) {
918 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
919 scno);
920 return -1;
921 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000922
Roland McGrathf691bd22006-04-25 07:34:41 +0000923 /*
924 * Fixup the syscall number
925 */
926 scno &= 0x000fffff;
927 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000928 }
Roland McGrath56703312008-05-20 01:35:55 +0000929 if (scno & 0x0f0000) {
930 /*
931 * Handle ARM specific syscall
932 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000933 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +0000934 scno &= 0x0000ffff;
935 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000936 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +0000937
Roland McGrath0f87c492003-06-03 23:29:04 +0000938 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200939 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
940 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000941 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000942# elif defined (M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000943 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000944 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000945# elif defined (LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +0000946 unsigned long long regs[38];
947
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200948 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +0000949 return -1;
950 a3 = regs[REG_A3];
951 r2 = regs[REG_V0];
952
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200953 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200954 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200955 if (a3 == 0 || a3 == -1) {
956 if (debug)
957 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000958 return 0;
959 }
Roland McGrath542c2c62008-05-20 01:11:56 +0000960 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000961# elif defined (MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000962 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000963 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200964 if (upeek(tcp, REG_V0, &scno) < 0)
965 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000966
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200967 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200968 if (a3 == 0 || a3 == -1) {
969 if (debug)
970 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000971 return 0;
972 }
Wichert Akkermanf90da011999-10-31 21:15:38 +0000973 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000974# elif defined (ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000975 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000976 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200977 if (upeek(tcp, REG_R0, &scno) < 0)
978 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000979
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200980 /*
981 * Do some sanity checks to figure out if it's
982 * really a syscall entry
983 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200984 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200985 if (a3 == 0 || a3 == -1) {
986 if (debug)
987 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000988 return 0;
989 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000990 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000991# elif defined (SPARC) || defined (SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000992 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000993 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000994 return -1;
995
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200996 /* Disassemble the syscall trap. */
997 /* Retrieve the syscall trap instruction. */
998 errno = 0;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +0000999# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001000 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1001 trap >>= 32;
Mike Frysinger8566c502009-10-12 11:05:14 -04001002# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001003 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001004# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001005 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001006 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001007
1008 /* Disassemble the trap to see what personality to use. */
1009 switch (trap) {
1010 case 0x91d02010:
1011 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001012 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001013 break;
1014 case 0x91d0206d:
1015 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001016 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001017 break;
1018 case 0x91d02000:
1019 /* SunOS syscall trap. (pers 1) */
1020 fprintf(stderr, "syscall: SunOS no support\n");
1021 return -1;
1022 case 0x91d02008:
1023 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001024 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001025 break;
1026 case 0x91d02009:
1027 /* NetBSD/FreeBSD syscall trap. */
1028 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1029 return -1;
1030 case 0x91d02027:
1031 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001032 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001033 break;
1034 default:
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001035# if defined (SPARC64)
1036 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
1037# else
1038 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
1039# endif
1040 return -1;
1041 }
1042
1043 /* Extract the system call number from the registers. */
1044 if (trap == 0x91d02027)
1045 scno = 156;
1046 else
1047 scno = regs.u_regs[U_REG_G1];
1048 if (scno == 0) {
1049 scno = regs.u_regs[U_REG_O0];
1050 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1051 }
1052# elif defined(HPPA)
1053 if (upeek(tcp, PT_GR20, &scno) < 0)
1054 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001055# elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001056 /*
1057 * In the new syscall ABI, the system call number is in R3.
1058 */
1059 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1060 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001061
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001062 if (scno < 0) {
1063 /* Odd as it may seem, a glibc bug has been known to cause
1064 glibc to issue bogus negative syscall numbers. So for
1065 our purposes, make strace print what it *should* have been */
1066 long correct_scno = (scno & 0xff);
1067 if (debug)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001068 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001069 "Detected glibc bug: bogus system call"
1070 " number = %ld, correcting to %ld\n",
1071 scno,
1072 correct_scno);
1073 scno = correct_scno;
1074 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001075# elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001076 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001077 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001078 scno &= 0xFFFF;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001079# elif defined(CRISV10) || defined(CRISV32)
1080 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1081 return -1;
Chris Metcalfc8c66982009-12-28 10:00:15 -05001082# elif defined(TILE)
1083 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1084 return -1;
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001085# elif defined(MICROBLAZE)
1086 if (upeek(tcp, 0, &scno) < 0)
1087 return -1;
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001088# endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001089
Denys Vlasenkoed720fd2012-02-25 02:24:03 +01001090#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001091 /* new syscall ABI returns result in R0 */
1092 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1093 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001094#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001095 /* ABI defines result returned in r9 */
1096 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1097 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001098#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001099
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001100
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001101 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001102 return 1;
1103}
1104
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001105/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001106 * Returns:
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001107 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
Roland McGratheb9e2e82009-06-02 16:49:22 -07001108 * 1: ok, continue in trace_syscall().
1109 * other: error, trace_syscall() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001110 * ("????" etc) and bail out.
1111 */
Roland McGratha4d48532005-06-08 20:45:28 +00001112static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001113syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001114{
Pavel Machek4dc3b142000-02-01 17:58:41 +00001115
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001116
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001117 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001118#if defined (I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001119 if (i386_regs.eax != -ENOSYS) {
1120 if (debug)
1121 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1122 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001123 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001124#elif defined (X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001125 {
1126 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001127 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001128 rax = (int)rax; /* sign extend from 32 bits */
1129 if (rax != -ENOSYS) {
Denys Vlasenko18beb982011-08-24 16:59:23 +02001130 if (debug)
1131 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1132 return 0;
1133 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001134 }
Michal Ludvig10a88d02002-10-07 14:31:00 +00001135#elif defined (S390) || defined (S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001136 /* TODO: we already fetched PT_GPR2 in get_scno
1137 * and stored it in syscall_mode, reuse it here
1138 * instead of re-fetching?
1139 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001140 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001141 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001142 if (syscall_mode != -ENOSYS)
1143 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001144 if (gpr2 != syscall_mode) {
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001145 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001146 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001147 return 0;
1148 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001149#elif defined (M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001150 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001151 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001152 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001153 if (d0 != -ENOSYS) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001155 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001156 return 0;
1157 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001158#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001159 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001160 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001161 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001162 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001163 if (ia32 && r8 != -ENOSYS) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001164 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001165 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001166 return 0;
1167 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001168#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001169 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001170 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001171 if (r10 != -ENOSYS) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001172 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001173 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001174 return 0;
1175 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001176#elif defined(MICROBLAZE)
1177 if (upeek(tcp, 3 * 4, &r3) < 0)
1178 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001179 if (r3 != -ENOSYS) {
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001180 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001181 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001182 return 0;
1183 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001184#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001185 return 1;
1186}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001187
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001188static int
1189internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001190{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001191 /*
1192 * We must always trace a few critical system calls in order to
1193 * correctly support following forks in the presence of tracing
1194 * qualifiers.
1195 */
1196 int (*func)();
1197
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001198 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001199 return 0;
1200
1201 func = sysent[tcp->scno].sys_func;
1202
1203 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001204 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001205 || sys_clone == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001206 )
1207 return internal_fork(tcp);
1208
Denys Vlasenko84703742012-02-25 02:38:52 +01001209#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001210 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001211# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001212 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001213# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001214 )
1215 return internal_exec(tcp);
Roland McGrathc1e45922008-05-27 23:18:29 +00001216#endif
1217
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001218 return 0;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001219}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001220
Roland McGratha4d48532005-06-08 20:45:28 +00001221static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001222syscall_enter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001223{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001224 int i, nargs;
1225
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001226 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001227 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001228 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001229 nargs = tcp->u_nargs = MAX_ARGS;
1230
1231# if defined(S390) || defined(S390X)
1232 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001233 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1234 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001235# elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001236 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001237 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1238 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001239# elif defined(IA64)
1240 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001241 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001242 long rbs_end;
1243 /* be backwards compatible with kernel < 2.4.4... */
1244# ifndef PT_RBS_END
1245# define PT_RBS_END PT_AR_BSP
1246# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001247
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001248 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1249 return -1;
1250 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001251 return -1;
1252
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001253 sof = (cfm >> 0) & 0x7f;
1254 sol = (cfm >> 7) & 0x7f;
1255 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1256
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001257 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001258 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1259 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1260 return -1;
1261 }
1262 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001263 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1264 PT_R9 /* ECX = out1 */,
1265 PT_R10 /* EDX = out2 */,
1266 PT_R14 /* ESI = out3 */,
1267 PT_R15 /* EDI = out4 */,
1268 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001269
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001270 for (i = 0; i < nargs; ++i) {
1271 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1272 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001273 /* truncate away IVE sign-extension */
1274 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001275 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001276 }
1277# elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
1278 /* N32 and N64 both use up to six registers. */
1279 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001280
1281 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1282 return -1;
1283
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001284 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001285 tcp->u_arg[i] = regs[REG_A0 + i];
1286# if defined(LINUX_MIPSN32)
1287 tcp->ext_arg[i] = regs[REG_A0 + i];
1288# endif
1289 }
1290# elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001291 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001292 long sp;
1293
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001294 if (upeek(tcp, REG_SP, &sp) < 0)
1295 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001296 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001297 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1298 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001299 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001300 (char *)(tcp->u_arg + 4));
1301 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001302 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001303 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001304 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001305 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001306# elif defined(POWERPC)
1307# ifndef PT_ORIG_R3
1308# define PT_ORIG_R3 34
1309# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001310 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001311 if (upeek(tcp, (i==0) ?
1312 (sizeof(unsigned long) * PT_ORIG_R3) :
1313 ((i+PT_R3) * sizeof(unsigned long)),
1314 &tcp->u_arg[i]) < 0)
1315 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001316 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001317# elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001318 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001319 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
1320# elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001321 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001322 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1323 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001324# elif defined(ARM)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001325 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001326 tcp->u_arg[i] = regs.uregs[i];
1327# elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001328 (void)i;
1329 (void)nargs;
1330 tcp->u_arg[0] = regs.r12;
1331 tcp->u_arg[1] = regs.r11;
1332 tcp->u_arg[2] = regs.r10;
1333 tcp->u_arg[3] = regs.r9;
1334 tcp->u_arg[4] = regs.r5;
1335 tcp->u_arg[5] = regs.r3;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001336# elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001337 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 +02001338
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001339 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001340 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1341 return -1;
1342# elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001343 static const int syscall_regs[MAX_ARGS] = {
1344 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1345 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001346 };
1347
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001348 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001349 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001350 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001351# elif defined(SH64)
1352 int i;
1353 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001354 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001355
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001356 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001357 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1358 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001359# elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001360 (void)i;
1361 (void)nargs;
1362 if (current_personality == 0) { /* x86-64 ABI */
1363 tcp->u_arg[0] = x86_64_regs.rdi;
1364 tcp->u_arg[1] = x86_64_regs.rsi;
1365 tcp->u_arg[2] = x86_64_regs.rdx;
1366 tcp->u_arg[3] = x86_64_regs.r10;
1367 tcp->u_arg[4] = x86_64_regs.r8;
1368 tcp->u_arg[5] = x86_64_regs.r9;
1369 } else { /* i386 ABI */
1370 /* Sign-extend lower 32 bits */
1371 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1372 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1373 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1374 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1375 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1376 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1377 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001378# elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001379 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001380 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1381 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001382# elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001383 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001384 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001385 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001386 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001387
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001388 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001389 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1390 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001391# elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001392 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001393 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1394 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001395# elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001396 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001397 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1398 return -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001399# elif defined(I386)
1400 (void)i;
1401 (void)nargs;
1402 tcp->u_arg[0] = i386_regs.ebx;
1403 tcp->u_arg[1] = i386_regs.ecx;
1404 tcp->u_arg[2] = i386_regs.edx;
1405 tcp->u_arg[3] = i386_regs.esi;
1406 tcp->u_arg[4] = i386_regs.edi;
1407 tcp->u_arg[5] = i386_regs.ebp;
1408# else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001409 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001410 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1411 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001412# endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001413 return 1;
1414}
1415
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001416static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001417trace_syscall_entering(struct tcb *tcp)
1418{
1419 int res, scno_good;
1420
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001421#if defined TCB_WAITEXECVE
1422 if (tcp->flags & TCB_WAITEXECVE) {
1423 /* This is the post-execve SIGTRAP. */
1424 tcp->flags &= ~TCB_WAITEXECVE;
1425 return 0;
1426 }
1427#endif
1428
Denys Vlasenko06602d92011-08-24 17:53:52 +02001429 scno_good = res = get_scno(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001430 if (res == 0)
1431 return res;
1432 if (res == 1)
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001433 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001434 if (res == 0)
1435 return res;
1436 if (res == 1)
1437 res = syscall_enter(tcp);
1438 if (res == 0)
1439 return res;
1440
1441 if (res != 1) {
1442 printleader(tcp);
1443 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001444 if (scno_good != 1)
1445 tprintf("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001446 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001447 tprintf("syscall_%lu(", tcp->scno);
1448 else
1449 tprintf("%s(", sysent[tcp->scno].sys_name);
1450 /*
1451 * " <unavailable>" will be added later by the code which
1452 * detects ptrace errors.
1453 */
1454 goto ret;
1455 }
1456
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001457#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1458 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001459#ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001460 if (sysent[tcp->scno].sys_func == sys_socketcall) {
1461 decode_subcall(tcp, SYS_socket_subcall,
1462 SYS_socket_nsubcalls, deref_style);
1463 break;
1464 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001465#endif
1466#ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001467 if (sysent[tcp->scno].sys_func == sys_ipc) {
1468 decode_subcall(tcp, SYS_ipc_subcall,
1469 SYS_ipc_nsubcalls, shift_style);
1470 break;
1471 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001472#endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001473 break;
1474 }
1475#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1476
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001477
1478 internal_syscall(tcp);
1479
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001480 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001481 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1482 (tracing_paths && !pathtrace_match(tcp))) {
1483 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1484 return 0;
1485 }
1486
1487 tcp->flags &= ~TCB_FILTERED;
1488
1489 if (cflag == CFLAG_ONLY_STATS) {
1490 res = 0;
1491 goto ret;
1492 }
1493
1494 printleader(tcp);
1495 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001496 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001497 tprintf("syscall_%lu(", tcp->scno);
1498 else
1499 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001500 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001501 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1502 sysent[tcp->scno].sys_func != sys_exit))
1503 res = printargs(tcp);
1504 else
1505 res = (*sysent[tcp->scno].sys_func)(tcp);
1506
1507 if (fflush(tcp->outf) == EOF)
1508 return -1;
1509 ret:
1510 tcp->flags |= TCB_INSYSCALL;
1511 /* Measure the entrance time as late as possible to avoid errors. */
1512 if (dtime || cflag)
1513 gettimeofday(&tcp->etime, NULL);
1514 return res;
1515}
1516
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001517/* Returns:
1518 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1519 * 1: ok, continue in trace_syscall().
1520 * other: error, trace_syscall() should print error indicator
1521 * ("????" etc) and bail out.
1522 */
1523static int
1524get_syscall_result(struct tcb *tcp)
1525{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001526# if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001527 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1528 return -1;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001529# elif defined (POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001530# define SO_MASK 0x10000000
1531 {
1532 long flags;
1533 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1534 return -1;
1535 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &result) < 0)
1536 return -1;
1537 if (flags & SO_MASK)
1538 result = -result;
1539 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001540# elif defined(AVR32)
1541 /* Read complete register set in one go. */
1542 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1543 return -1;
1544# elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001545 if (upeek(tcp, PT_R0, &r0) < 0)
1546 return -1;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001547# elif defined (I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001548 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001549 return -1;
1550# elif defined (X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001551 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001552 return -1;
1553# elif defined(IA64)
1554# define IA64_PSR_IS ((long)1 << 34)
1555 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1556 ia32 = (psr & IA64_PSR_IS) != 0;
1557 if (upeek(tcp, PT_R8, &r8) < 0)
1558 return -1;
1559 if (upeek(tcp, PT_R10, &r10) < 0)
1560 return -1;
1561# elif defined (ARM)
1562 /* Read complete register set in one go. */
1563 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1564 return -1;
1565# elif defined (M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001566 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1567 return -1;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001568# elif defined (LINUX_MIPSN32)
1569 unsigned long long regs[38];
1570
1571 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1572 return -1;
1573 a3 = regs[REG_A3];
1574 r2 = regs[REG_V0];
1575# elif defined (MIPS)
1576 if (upeek(tcp, REG_A3, &a3) < 0)
1577 return -1;
1578 if (upeek(tcp, REG_V0, &r2) < 0)
1579 return -1;
1580# elif defined (ALPHA)
1581 if (upeek(tcp, REG_A3, &a3) < 0)
1582 return -1;
1583 if (upeek(tcp, REG_R0, &r0) < 0)
1584 return -1;
1585# elif defined (SPARC) || defined (SPARC64)
1586 /* Everything we need is in the current register set. */
1587 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1588 return -1;
1589# elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001590 if (upeek(tcp, PT_GR28, &r28) < 0)
1591 return -1;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001592# elif defined(SH)
1593# elif defined(SH64)
1594# elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001595 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1596 return -1;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001597# elif defined(TILE)
1598# elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001599 if (upeek(tcp, 3 * 4, &r3) < 0)
1600 return -1;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001601# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001602
Denys Vlasenkoed720fd2012-02-25 02:24:03 +01001603#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001604 /* new syscall ABI returns result in R0 */
1605 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1606 return -1;
1607#elif defined(SH64)
1608 /* ABI defines result returned in r9 */
1609 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1610 return -1;
1611#endif
1612
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001613
1614 return 1;
1615}
1616
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001617/* Called at each syscall exit.
1618 * Returns:
1619 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1620 * 1: ok, continue in trace_syscall().
1621 * other: error, trace_syscall() should print error indicator
1622 * ("????" etc) and bail out.
1623 */
1624static int
1625syscall_fixup_on_sysexit(struct tcb *tcp)
1626{
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001627
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001628
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001629# if defined (S390) || defined (S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001630 if (syscall_mode != -ENOSYS)
1631 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001632 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001633 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1634 /*
1635 * Return from execve.
1636 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1637 * flag set for the post-execve SIGTRAP to see and reset.
1638 */
1639 gpr2 = 0;
1640 }
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001641# endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001642 return 1;
1643}
1644
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001645/*
1646 * Check the syscall return value register value for whether it is
1647 * a negated errno code indicating an error, or a success return value.
1648 */
1649static inline int
1650is_negated_errno(unsigned long int val)
1651{
1652 unsigned long int max = -(long int) nerrnos;
1653# if SUPPORTED_PERSONALITIES > 1
1654 if (personality_wordsize[current_personality] < sizeof(val)) {
1655 val = (unsigned int) val;
1656 max = (unsigned int) max;
1657 }
1658# endif
1659 return val > max;
1660}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001661
1662static int
1663get_error(struct tcb *tcp)
1664{
1665 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001666 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001667 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001668 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1669 check_errno = 0;
1670 }
1671# if defined(S390) || defined(S390X)
1672 if (check_errno && is_negated_errno(gpr2)) {
1673 tcp->u_rval = -1;
1674 u_error = -gpr2;
1675 }
1676 else {
1677 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001678 }
1679# elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001680 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001681 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001682 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001683 }
1684 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001685 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001686 }
1687# elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001688 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001689 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001690 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001691 }
1692 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001693 tcp->u_rval = x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001694 }
1695# elif defined(IA64)
1696 if (ia32) {
1697 int err;
1698
1699 err = (int)r8;
1700 if (check_errno && is_negated_errno(err)) {
1701 tcp->u_rval = -1;
1702 u_error = -err;
1703 }
1704 else {
1705 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001706 }
1707 } else {
1708 if (check_errno && r10) {
1709 tcp->u_rval = -1;
1710 u_error = r8;
1711 } else {
1712 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001713 }
1714 }
1715# elif defined(MIPS)
1716 if (check_errno && a3) {
1717 tcp->u_rval = -1;
1718 u_error = r2;
1719 } else {
1720 tcp->u_rval = r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001721 }
1722# elif defined(POWERPC)
1723 if (check_errno && is_negated_errno(result)) {
1724 tcp->u_rval = -1;
1725 u_error = -result;
1726 }
1727 else {
1728 tcp->u_rval = result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001729 }
1730# elif defined(M68K)
1731 if (check_errno && is_negated_errno(d0)) {
1732 tcp->u_rval = -1;
1733 u_error = -d0;
1734 }
1735 else {
1736 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001737 }
1738# elif defined(ARM)
1739 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1740 tcp->u_rval = -1;
1741 u_error = -regs.ARM_r0;
1742 }
1743 else {
1744 tcp->u_rval = regs.ARM_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001745 }
1746# elif defined(AVR32)
1747 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1748 tcp->u_rval = -1;
1749 u_error = -regs.r12;
1750 }
1751 else {
1752 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001753 }
1754# elif defined(BFIN)
1755 if (check_errno && is_negated_errno(r0)) {
1756 tcp->u_rval = -1;
1757 u_error = -r0;
1758 } else {
1759 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001760 }
1761# elif defined(ALPHA)
1762 if (check_errno && a3) {
1763 tcp->u_rval = -1;
1764 u_error = r0;
1765 }
1766 else {
1767 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001768 }
1769# elif defined(SPARC)
1770 if (check_errno && regs.psr & PSR_C) {
1771 tcp->u_rval = -1;
1772 u_error = regs.u_regs[U_REG_O0];
1773 }
1774 else {
1775 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001776 }
1777# elif defined(SPARC64)
1778 if (check_errno && regs.tstate & 0x1100000000UL) {
1779 tcp->u_rval = -1;
1780 u_error = regs.u_regs[U_REG_O0];
1781 }
1782 else {
1783 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001784 }
1785# elif defined(HPPA)
1786 if (check_errno && is_negated_errno(r28)) {
1787 tcp->u_rval = -1;
1788 u_error = -r28;
1789 }
1790 else {
1791 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001792 }
1793# elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001794 if (check_errno && is_negated_errno(r0)) {
1795 tcp->u_rval = -1;
1796 u_error = -r0;
1797 }
1798 else {
1799 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001800 }
1801# elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001802 if (check_errno && is_negated_errno(r9)) {
1803 tcp->u_rval = -1;
1804 u_error = -r9;
1805 }
1806 else {
1807 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001808 }
1809# elif defined(CRISV10) || defined(CRISV32)
1810 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1811 tcp->u_rval = -1;
1812 u_error = -r10;
1813 }
1814 else {
1815 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001816 }
1817# elif defined(TILE)
1818 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001819 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1820 return -1;
1821 if (check_errno && rval < 0 && rval > -nerrnos) {
1822 tcp->u_rval = -1;
1823 u_error = -rval;
1824 }
1825 else {
1826 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001827 }
1828# elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001829 if (check_errno && is_negated_errno(r3)) {
1830 tcp->u_rval = -1;
1831 u_error = -r3;
1832 }
1833 else {
1834 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001835 }
1836# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001837 tcp->u_error = u_error;
1838 return 1;
1839}
1840
1841static void
1842dumpio(struct tcb *tcp)
1843{
1844 if (syserror(tcp))
1845 return;
1846 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1847 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001848 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001849 return;
1850 if (sysent[tcp->scno].sys_func == printargs)
1851 return;
1852 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1853 if (sysent[tcp->scno].sys_func == sys_read ||
1854 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001855 sysent[tcp->scno].sys_func == sys_recv ||
1856 sysent[tcp->scno].sys_func == sys_recvfrom)
1857 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1858 else if (sysent[tcp->scno].sys_func == sys_readv)
1859 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1860 return;
1861 }
1862 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1863 if (sysent[tcp->scno].sys_func == sys_write ||
1864 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001865 sysent[tcp->scno].sys_func == sys_send ||
1866 sysent[tcp->scno].sys_func == sys_sendto)
1867 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1868 else if (sysent[tcp->scno].sys_func == sys_writev)
1869 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1870 return;
1871 }
1872}
1873
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001874static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001875trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001876{
1877 int sys_res;
1878 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001879 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001880 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001881
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001882 /* Measure the exit time as early as possible to avoid errors. */
1883 if (dtime || cflag)
1884 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001885
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001886#if SUPPORTED_PERSONALITIES > 1
1887 update_personality(tcp, tcp->currpers);
1888#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001889 res = get_syscall_result(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001890 if (res == 0)
1891 return res;
1892 if (res == 1)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001893 res = syscall_fixup_on_sysexit(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001894 if (res == 0)
1895 return res;
1896 if (res == 1)
1897 res = get_error(tcp);
1898 if (res == 0)
1899 return res;
1900 if (res == 1)
1901 internal_syscall(tcp);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001902
Grant Edwards8a082772011-04-07 20:25:40 +00001903 if (res == 1 && filtered(tcp)) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001904 goto ret;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001905 }
1906
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001907 if (tcp->flags & TCB_REPRINT) {
1908 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001909 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001910 tprintf("<... syscall_%lu resumed> ", tcp->scno);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001911 else
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001912 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001913 }
1914
1915 if (cflag) {
1916 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02001917 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02001918 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001919 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001920 }
1921 }
1922
1923 if (res != 1) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001924 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001925 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01001926 tprints("= ? <unavailable>\n");
1927 printing_tcp = NULL;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001928 tcp->flags &= ~TCB_INSYSCALL;
1929 return res;
1930 }
1931
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001932 if (!SCNO_IN_RANGE(tcp->scno)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001933 || (qual_flags[tcp->scno] & QUAL_RAW))
1934 sys_res = printargs(tcp);
1935 else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001936 /* FIXME: not_failing_only (IOW, option -z) is broken:
1937 * failure of syscall is known only after syscall return.
1938 * Thus we end up with something like this on, say, ENOENT:
1939 * open("doesnt_exist", O_RDONLY <unfinished ...>
1940 * {next syscall decode}
1941 * whereas the intended result is that open(...) line
1942 * is not shown at all.
1943 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001944 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02001945 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001946 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
1947 }
1948
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001949 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001950 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02001951 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001952 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001953 qual_flags[tcp->scno] & QUAL_RAW) {
1954 if (u_error)
1955 tprintf("= -1 (errno %ld)", u_error);
1956 else
1957 tprintf("= %#lx", tcp->u_rval);
1958 }
1959 else if (!(sys_res & RVAL_NONE) && u_error) {
1960 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01001961 /* Blocked signals do not interrupt any syscalls.
1962 * In this case syscalls don't return ERESTARTfoo codes.
1963 *
1964 * Deadly signals set to SIG_DFL interrupt syscalls
1965 * and kill the process regardless of which of the codes below
1966 * is returned by the interrupted syscall.
1967 * In some cases, kernel forces a kernel-generated deadly
1968 * signal to be unblocked and set to SIG_DFL (and thus cause
1969 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
1970 * or SIGILL. (The alternative is to leave process spinning
1971 * forever on the faulty instruction - not useful).
1972 *
1973 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
1974 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
1975 * but kernel will always restart them.
1976 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001977 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01001978 /* Most common type of signal-interrupted syscall exit code.
1979 * The system call will be restarted with the same arguments
1980 * if SA_RESTART is set; otherwise, it will fail with EINTR.
1981 */
1982 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001983 break;
1984 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01001985 /* Rare. For example, fork() returns this if interrupted.
1986 * SA_RESTART is ignored (assumed set): the restart is unconditional.
1987 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001988 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001989 break;
1990 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01001991 /* pause(), rt_sigsuspend() etc use this code.
1992 * SA_RESTART is ignored (assumed not set):
1993 * syscall won't restart (will return EINTR instead)
1994 * even after signal with SA_RESTART set.
1995 * However, after SIG_IGN or SIG_DFL signal it will.
1996 */
1997 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001998 break;
1999 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002000 /* Syscalls like nanosleep(), poll() which can't be
2001 * restarted with their original arguments use this
2002 * code. Kernel will execute restart_syscall() instead,
2003 * which changes arguments before restarting syscall.
2004 * SA_RESTART is ignored (assumed not set) similarly
2005 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2006 * since restart data is saved in "restart block"
2007 * in task struct, and if signal handler uses a syscall
2008 * which in turn saves another such restart block,
2009 * old data is lost and restart becomes impossible)
2010 */
2011 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002012 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002013 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002014 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002015 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002016 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002017 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002018 strerror(u_error));
2019 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002020 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002021 strerror(u_error));
2022 break;
2023 }
2024 if ((sys_res & RVAL_STR) && tcp->auxstr)
2025 tprintf(" (%s)", tcp->auxstr);
2026 }
2027 else {
2028 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002029 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002030 else {
2031 switch (sys_res & RVAL_MASK) {
2032 case RVAL_HEX:
2033 tprintf("= %#lx", tcp->u_rval);
2034 break;
2035 case RVAL_OCTAL:
2036 tprintf("= %#lo", tcp->u_rval);
2037 break;
2038 case RVAL_UDECIMAL:
2039 tprintf("= %lu", tcp->u_rval);
2040 break;
2041 case RVAL_DECIMAL:
2042 tprintf("= %ld", tcp->u_rval);
2043 break;
2044#ifdef HAVE_LONG_LONG
2045 case RVAL_LHEX:
2046 tprintf("= %#llx", tcp->u_lrval);
2047 break;
2048 case RVAL_LOCTAL:
2049 tprintf("= %#llo", tcp->u_lrval);
2050 break;
2051 case RVAL_LUDECIMAL:
2052 tprintf("= %llu", tcp->u_lrval);
2053 break;
2054 case RVAL_LDECIMAL:
2055 tprintf("= %lld", tcp->u_lrval);
2056 break;
2057#endif
2058 default:
2059 fprintf(stderr,
2060 "invalid rval format\n");
2061 break;
2062 }
2063 }
2064 if ((sys_res & RVAL_STR) && tcp->auxstr)
2065 tprintf(" (%s)", tcp->auxstr);
2066 }
2067 if (dtime) {
2068 tv_sub(&tv, &tv, &tcp->etime);
2069 tprintf(" <%ld.%06ld>",
2070 (long) tv.tv_sec, (long) tv.tv_usec);
2071 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002072 tprints("\n");
2073 printing_tcp = NULL;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002074
2075 dumpio(tcp);
2076 if (fflush(tcp->outf) == EOF)
2077 return -1;
Denys Vlasenko3b738812011-08-22 02:06:35 +02002078 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002079 tcp->flags &= ~TCB_INSYSCALL;
2080 return 0;
2081}
2082
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002083int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002084trace_syscall(struct tcb *tcp)
2085{
2086 return exiting(tcp) ?
2087 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2088}