blob: 8eedb12efe29a42f32378c80f3aecb0855dd9a81 [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
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000038#include <sys/user.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000039#include <sys/param.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000040
Wichert Akkerman15dea971999-10-06 13:06:34 +000041#ifdef HAVE_SYS_REG_H
Denys Vlasenko523635f2012-02-25 02:44:25 +010042# include <sys/reg.h>
43# ifndef PTRACE_PEEKUSR
44# define PTRACE_PEEKUSR PTRACE_PEEKUSER
45# endif
Wichert Akkermanfaf72222000-02-19 23:59:03 +000046#elif defined(HAVE_LINUX_PTRACE_H)
Denys Vlasenko523635f2012-02-25 02:44:25 +010047# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000048# ifdef HAVE_STRUCT_IA64_FPREG
49# define ia64_fpreg XXX_ia64_fpreg
50# endif
51# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
52# define pt_all_user_regs XXX_pt_all_user_regs
53# endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010054# include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000055# undef ia64_fpreg
56# undef pt_all_user_regs
Wichert Akkerman15dea971999-10-06 13:06:34 +000057#endif
58
Denys Vlasenko84703742012-02-25 02:38:52 +010059#if defined(SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +000060# undef PTRACE_GETREGS
61# define PTRACE_GETREGS PTRACE_GETREGS64
62# undef PTRACE_SETREGS
63# define PTRACE_SETREGS PTRACE_SETREGS64
Denys Vlasenko84703742012-02-25 02:38:52 +010064#endif
Roland McGrath6d1a65c2004-07-12 07:44:08 +000065
Denys Vlasenko84703742012-02-25 02:38:52 +010066#if defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000067# include <asm/ptrace_offsets.h>
68# include <asm/rse.h>
69#endif
70
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000071#ifndef ERESTARTSYS
Denys Vlasenko523635f2012-02-25 02:44:25 +010072# define ERESTARTSYS 512
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000073#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010074# ifndef ERESTARTNOINTR
75# define ERESTARTNOINTR 513
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000076#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010077# ifndef ERESTARTNOHAND
78# define ERESTARTNOHAND 514 /* restart if no handler.. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000079#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010080# ifndef ENOIOCTLCMD
81# define ENOIOCTLCMD 515 /* No ioctl command */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000082#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010083# ifndef ERESTART_RESTARTBLOCK
84# define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
Roland McGrath9c555e72003-07-09 09:47:59 +000085#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010086
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000087#ifndef NSIG
Denys Vlasenko523635f2012-02-25 02:44:25 +010088# warning: NSIG is not defined, using 32
89# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000090#endif
91#ifdef ARM
Denys Vlasenko041b3ee2011-08-18 12:48:56 +020092/* Ugh. Is this really correct? ARM has no RT signals?! */
Denys Vlasenko523635f2012-02-25 02:44:25 +010093# undef NSIG
94# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000095#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000096
97#include "syscall.h"
98
99/* Define these shorthand notations to simplify the syscallent files. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000100#define TD TRACE_DESC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000101#define TF TRACE_FILE
102#define TI TRACE_IPC
103#define TN TRACE_NETWORK
104#define TP TRACE_PROCESS
105#define TS TRACE_SIGNAL
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000106#define NF SYSCALL_NEVER_FAILS
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200107#define MA MAX_ARGS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000108
Roland McGrathee36ce12004-09-04 03:53:10 +0000109static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000110#include "syscallent.h"
111};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000112
113#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000114static const struct sysent sysent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100115# include "syscallent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000116};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200117#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118
119#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000120static const struct sysent sysent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100121# include "syscallent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200123#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000124
125/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000126#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000127#undef TF
128#undef TI
129#undef TN
130#undef TP
131#undef TS
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000132#undef NF
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200133#undef MA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000134
Denys Vlasenko39fca622011-08-20 02:12:33 +0200135/*
136 * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
137 * program `ioctlsort', such that the list is sorted by the `code' field.
138 * This has the side-effect of resolving the _IO.. macros into
139 * plain integers, eliminating the need to include here everything
140 * in "/usr/include".
141 */
142
Roland McGrathee36ce12004-09-04 03:53:10 +0000143static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000144#include "errnoent.h"
145};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200146static const char *const signalent0[] = {
147#include "signalent.h"
148};
149static const struct ioctlent ioctlent0[] = {
150#include "ioctlent.h"
151};
152enum { nsyscalls0 = ARRAY_SIZE(sysent0) };
153enum { nerrnos0 = ARRAY_SIZE(errnoent0) };
154enum { nsignals0 = ARRAY_SIZE(signalent0) };
155enum { nioctlents0 = ARRAY_SIZE(ioctlent0) };
156int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000157
158#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000159static const char *const errnoent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100160# include "errnoent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000161};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200162static const char *const signalent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100163# include "signalent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200164};
165static const struct ioctlent ioctlent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100166# include "ioctlent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200167};
168enum { nsyscalls1 = ARRAY_SIZE(sysent1) };
169enum { nerrnos1 = ARRAY_SIZE(errnoent1) };
170enum { nsignals1 = ARRAY_SIZE(signalent1) };
171enum { nioctlents1 = ARRAY_SIZE(ioctlent1) };
172int qual_flags1[MAX_QUALS];
173#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000174
175#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000176static const char *const errnoent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100177# include "errnoent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000178};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200179static const char *const signalent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100180# include "signalent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200181};
182static const struct ioctlent ioctlent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100183# include "ioctlent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200184};
185enum { nsyscalls2 = ARRAY_SIZE(sysent2) };
186enum { nerrnos2 = ARRAY_SIZE(errnoent2) };
187enum { nsignals2 = ARRAY_SIZE(signalent2) };
188enum { nioctlents2 = ARRAY_SIZE(ioctlent2) };
189int qual_flags2[MAX_QUALS];
190#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000191
Denys Vlasenko39fca622011-08-20 02:12:33 +0200192const struct sysent *sysent;
Roland McGrathee36ce12004-09-04 03:53:10 +0000193const char *const *errnoent;
Denys Vlasenko39fca622011-08-20 02:12:33 +0200194const char *const *signalent;
195const struct ioctlent *ioctlent;
Denys Vlasenkoafc64032011-08-23 13:29:01 +0200196unsigned nsyscalls;
197unsigned nerrnos;
198unsigned nsignals;
199unsigned nioctlents;
Denys Vlasenko39fca622011-08-20 02:12:33 +0200200int *qual_flags;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000201
202int current_personality;
203
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000204#ifndef PERSONALITY0_WORDSIZE
205# define PERSONALITY0_WORDSIZE sizeof(long)
206#endif
207const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
208 PERSONALITY0_WORDSIZE,
209#if SUPPORTED_PERSONALITIES > 1
210 PERSONALITY1_WORDSIZE,
211#endif
212#if SUPPORTED_PERSONALITIES > 2
213 PERSONALITY2_WORDSIZE,
214#endif
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200215};
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000216
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200217void
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000218set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000219{
220 switch (personality) {
221 case 0:
222 errnoent = errnoent0;
223 nerrnos = nerrnos0;
224 sysent = sysent0;
225 nsyscalls = nsyscalls0;
226 ioctlent = ioctlent0;
227 nioctlents = nioctlents0;
228 signalent = signalent0;
229 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000230 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000231 break;
232
233#if SUPPORTED_PERSONALITIES >= 2
234 case 1:
235 errnoent = errnoent1;
236 nerrnos = nerrnos1;
237 sysent = sysent1;
238 nsyscalls = nsyscalls1;
239 ioctlent = ioctlent1;
240 nioctlents = nioctlents1;
241 signalent = signalent1;
242 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000243 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000244 break;
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200245#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000246
247#if SUPPORTED_PERSONALITIES >= 3
248 case 2:
249 errnoent = errnoent2;
250 nerrnos = nerrnos2;
251 sysent = sysent2;
252 nsyscalls = nsyscalls2;
253 ioctlent = ioctlent2;
254 nioctlents = nioctlents2;
255 signalent = signalent2;
256 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000257 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000258 break;
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200259#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000260 }
261
262 current_personality = personality;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000263}
264
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000265#if SUPPORTED_PERSONALITIES > 1
266static void
267update_personality(struct tcb *tcp, int personality)
268{
269 if (personality == current_personality)
270 return;
271 set_personality(personality);
272
273 if (personality == tcp->currpers)
274 return;
275 tcp->currpers = personality;
276
Denys Vlasenko523635f2012-02-25 02:44:25 +0100277# if defined(POWERPC64) || defined(X86_64)
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000278 if (!qflag) {
279 static const char *const names[] = {"64 bit", "32 bit"};
280 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
281 tcp->pid, names[personality]);
282 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100283# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000284}
285#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000286
Roland McGrath9797ceb2002-12-30 10:23:00 +0000287static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000288
Roland McGrathe10e62a2004-09-04 04:20:43 +0000289static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000290 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000291 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000292 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000293 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000294} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000295 { QUAL_TRACE, "trace", qual_syscall, "system call" },
296 { QUAL_TRACE, "t", qual_syscall, "system call" },
297 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
298 { QUAL_ABBREV, "a", qual_syscall, "system call" },
299 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
300 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
301 { QUAL_RAW, "raw", qual_syscall, "system call" },
302 { QUAL_RAW, "x", qual_syscall, "system call" },
303 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
304 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
305 { QUAL_SIGNAL, "s", qual_signal, "signal" },
306 { QUAL_FAULT, "fault", qual_fault, "fault" },
307 { QUAL_FAULT, "faults", qual_fault, "fault" },
308 { QUAL_FAULT, "m", qual_fault, "fault" },
309 { QUAL_READ, "read", qual_desc, "descriptor" },
310 { QUAL_READ, "reads", qual_desc, "descriptor" },
311 { QUAL_READ, "r", qual_desc, "descriptor" },
312 { QUAL_WRITE, "write", qual_desc, "descriptor" },
313 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
314 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000315 { 0, NULL, NULL, NULL },
316};
317
Roland McGrath9797ceb2002-12-30 10:23:00 +0000318static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000319qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000320{
Roland McGrath138c6a32006-01-12 09:50:49 +0000321 if (pers == 0 || pers < 0) {
322 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000323 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000324 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000325 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000326 }
327
328#if SUPPORTED_PERSONALITIES >= 2
329 if (pers == 1 || pers < 0) {
330 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000331 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000332 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000333 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000334 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100335#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000336
337#if SUPPORTED_PERSONALITIES >= 3
338 if (pers == 2 || pers < 0) {
339 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000340 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000341 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000342 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000343 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100344#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000345}
346
347static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000348qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000349{
350 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000351 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000352
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000353 if (isdigit((unsigned char)*s)) {
354 int i = atoi(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000355 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000356 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000357 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000358 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000359 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000360 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000361 if (strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000362 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000363 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000364 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000365
366#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000367 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000368 if (strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000369 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000370 rc = 0;
371 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100372#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000373
374#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000375 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000376 if (strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000377 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000378 rc = 0;
379 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100380#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000381
Roland McGrathfe6b3522005-02-02 04:40:11 +0000382 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000383}
384
385static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000386qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000387{
388 int i;
389 char buf[32];
390
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000391 if (isdigit((unsigned char)*s)) {
392 int signo = atoi(s);
393 if (signo < 0 || signo >= MAX_QUALS)
394 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000395 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000396 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000397 }
Roland McGrathd62b6712004-03-02 06:52:01 +0000398 if (strlen(s) >= sizeof buf)
Roland McGrathfe6b3522005-02-02 04:40:11 +0000399 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000400 strcpy(buf, s);
401 s = buf;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000402 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000403 s += 3;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000404 for (i = 0; i <= NSIG; i++)
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000405 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000406 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000407 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000408 }
Roland McGrath76421df2005-02-02 03:51:18 +0000409 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000410}
411
412static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000413qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000414{
415 return -1;
416}
417
418static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000419qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000420{
Roland McGrath48a035f2006-01-12 09:45:56 +0000421 if (isdigit((unsigned char)*s)) {
Roland McGrathfe6b3522005-02-02 04:40:11 +0000422 int desc = atoi(s);
423 if (desc < 0 || desc >= MAX_QUALS)
424 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000425 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000426 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000427 }
428 return -1;
429}
430
431static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000432lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000433{
434 if (strcmp(s, "file") == 0)
435 return TRACE_FILE;
436 if (strcmp(s, "ipc") == 0)
437 return TRACE_IPC;
438 if (strcmp(s, "network") == 0)
439 return TRACE_NETWORK;
440 if (strcmp(s, "process") == 0)
441 return TRACE_PROCESS;
442 if (strcmp(s, "signal") == 0)
443 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000444 if (strcmp(s, "desc") == 0)
445 return TRACE_DESC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000446 return -1;
447}
448
449void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000450qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000451{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000452 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000453 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000454 char *copy;
455 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000456 int i, n;
457
458 opt = &qual_options[0];
459 for (i = 0; (p = qual_options[i].option_name); i++) {
460 n = strlen(p);
461 if (strncmp(s, p, n) == 0 && s[n] == '=') {
462 opt = &qual_options[i];
463 s += n + 1;
464 break;
465 }
466 }
467 not = 0;
468 if (*s == '!') {
469 not = 1;
470 s++;
471 }
472 if (strcmp(s, "none") == 0) {
473 not = 1 - not;
474 s = "all";
475 }
476 if (strcmp(s, "all") == 0) {
477 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000478 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000479 }
480 return;
481 }
482 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000483 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000484 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200485 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200486 if (!copy)
487 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000488 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000489 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000490 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000491 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000492 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000493
494#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000495 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000496 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000497 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100498#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000499
500#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000501 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000502 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000503 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100504#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000505
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000506 continue;
507 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000508 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100509 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000510 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000511 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000512 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000513 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000514 return;
515}
516
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000517#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000518static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000519decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000520{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000521 unsigned long addr;
522 unsigned int i, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000523
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000524 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
525 return;
526
527 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
528 addr = tcp->u_arg[1];
529 tcp->u_nargs = sysent[tcp->scno].nargs;
530 size = personality_wordsize[current_personality];
531 for (i = 0; i < tcp->u_nargs; ++i) {
532 if (size == sizeof(int)) {
533 unsigned int arg;
534 if (umove(tcp, addr, &arg) < 0)
535 arg = 0;
536 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000537 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000538 else {
539 unsigned long arg;
540 if (umove(tcp, addr, &arg) < 0)
541 arg = 0;
542 tcp->u_arg[i] = arg;
543 }
544 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000545 }
546}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000547#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400548
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000549#ifdef SYS_ipc_subcall
550static void
551decode_ipc_subcall(struct tcb *tcp)
552{
553 unsigned int i;
554
555 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
556 return;
557
558 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
559 tcp->u_nargs = sysent[tcp->scno].nargs;
560 for (i = 0; i < tcp->u_nargs; i++)
561 tcp->u_arg[i] = tcp->u_arg[i + 1];
562}
563#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000564
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200565int
566printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000567{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200568 if (entering(tcp)) {
569 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000570
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200571 for (i = 0; i < tcp->u_nargs; i++)
572 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
573 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000574 return 0;
575}
576
Denys Vlasenko72879c62012-02-27 14:18:02 +0100577int
578printargs_lu(struct tcb *tcp)
579{
580 if (entering(tcp)) {
581 int i;
582
583 for (i = 0; i < tcp->u_nargs; i++)
584 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
585 }
586 return 0;
587}
588
589int
590printargs_ld(struct tcb *tcp)
591{
592 if (entering(tcp)) {
593 int i;
594
595 for (i = 0; i < tcp->u_nargs; i++)
596 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
597 }
598 return 0;
599}
600
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200601long
602getrval2(struct tcb *tcp)
603{
604 long val = -1;
605
Denys Vlasenko523635f2012-02-25 02:44:25 +0100606#if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200607 struct pt_regs regs;
608 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
609 return -1;
610 val = regs.u_regs[U_REG_O1];
611#elif defined(SH)
612 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
613 return -1;
614#elif defined(IA64)
615 if (upeek(tcp, PT_R9, &val) < 0)
616 return -1;
617#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200618
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200619 return val;
620}
621
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200622int
623is_restart_error(struct tcb *tcp)
624{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200625 switch (tcp->u_error) {
626 case ERESTARTSYS:
627 case ERESTARTNOINTR:
628 case ERESTARTNOHAND:
629 case ERESTART_RESTARTBLOCK:
630 return 1;
631 default:
632 break;
633 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200634 return 0;
635}
636
Denys Vlasenko523635f2012-02-25 02:44:25 +0100637#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100638struct pt_regs i386_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100639#elif defined(X86_64)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100640/*
641 * On 32 bits, pt_regs and user_regs_struct are the same,
642 * but on 64 bits, user_regs_struct has six more fields:
643 * fs_base, gs_base, ds, es, fs, gs.
644 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
645 */
646static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100647#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200648long r8, r10, psr; /* TODO: make static? */
649long ia32 = 0; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100650#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +0200651static long result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100652#elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200653static long d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100654#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200655static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100656#elif defined(ARM)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200657static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100658#elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200659static long r0;
660static long a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100661#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200662static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100663#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200664static struct pt_regs regs;
665static unsigned long trap;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100666#elif defined(LINUX_MIPSN32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200667static long long a3;
668static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100669#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200670static long a3;
671static long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100672#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200673static long gpr2;
674static long pc;
675static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100676#elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200677static long r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100678#elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200679static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100680#elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200681static long r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100682#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200683static long r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100684#elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200685static long r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100686#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000687
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200688/* Returns:
689 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
690 * 1: ok, continue in trace_syscall().
691 * other: error, trace_syscall() should print error indicator
692 * ("????" etc) and bail out.
693 */
Denys Vlasenko9a36ae52011-08-24 16:47:32 +0200694static
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000695int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200696get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000697{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000698 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000699
Denys Vlasenko523635f2012-02-25 02:44:25 +0100700#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000701 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200702 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000703
704 if (syscall_mode != -ENOSYS) {
705 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000706 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000707 */
708 scno = syscall_mode;
709 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000710 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000711 * Old style of "passing" the scno via the SVC instruction.
712 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000713 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200714 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200715 static const int gpr_offset[16] = {
716 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
717 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
718 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
719 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
720 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000721
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000722 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000723 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000724 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000725 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000726 if (errno) {
727 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000728 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000729 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000730
731 /*
732 * We have to check if the SVC got executed directly or via an
733 * EXECUTE instruction. In case of EXECUTE it is necessary to do
734 * instruction decoding to derive the system call number.
735 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
736 * so that this doesn't work if a SVC opcode is part of an EXECUTE
737 * opcode. Since there is no way to find out the opcode size this
738 * is the best we can do...
739 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000740 if ((opcode & 0xff00) == 0x0a00) {
741 /* SVC opcode */
742 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000743 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000744 else {
745 /* SVC got executed by EXECUTE instruction */
746
747 /*
748 * Do instruction decoding of EXECUTE. If you really want to
749 * understand this, read the Principles of Operations.
750 */
751 svc_addr = (void *) (opcode & 0xfff);
752
753 tmp = 0;
754 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000755 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000756 return -1;
757 svc_addr += tmp;
758
759 tmp = 0;
760 offset_reg = (opcode & 0x0000f000) >> 12;
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
Denys Vlasenkofb036672009-01-23 16:30:26 +0000765 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000766 if (errno)
767 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100768# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000769 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100770# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000771 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100772# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000773 tmp = 0;
774 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000775 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000776 return -1;
777
778 scno = (scno | tmp) & 0xff;
779 }
780 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100781#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000782 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000783 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100784# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200785 /* TODO: speed up strace by not doing this at every syscall.
786 * We only need to do it after execve.
787 */
788 int currpers;
789 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200790
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200791 /* Check for 64/32 bit mode. */
792 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
793 return -1;
794 /* SF is bit 0 of MSR */
795 if (val < 0)
796 currpers = 0;
797 else
798 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000799 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100800# endif
801#elif defined(AVR32)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200802 /* Read complete register set in one go. */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000803 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
804 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200805 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100806#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000807 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000808 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100809#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200810 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000811 return -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200812 scno = i386_regs.orig_eax;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100813#elif defined(X86_64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200814 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200815 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
816 return -1;
817 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +0000818
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200819 /* Check CS register value. On x86-64 linux it is:
820 * 0x33 for long mode (64 bit)
821 * 0x23 for compatibility mode (32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200822 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200823 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200824 case 0x23: currpers = 1; break;
825 case 0x33: currpers = 0; break;
826 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200827 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200828 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200829 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200830 currpers = current_personality;
831 break;
832 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100833# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200834 /* This version analyzes the opcode of a syscall instruction.
835 * (int 0x80 on i386 vs. syscall on x86-64)
836 * It works, but is too complicated.
837 */
838 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +0000839
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200840 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +0000841
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200842 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
843 rip -= 2;
844 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +0000845
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200846 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200847 if (errno)
848 fprintf(stderr, "ptrace_peektext failed: %s\n",
849 strerror(errno));
850 switch (call & 0xffff) {
851 /* x86-64: syscall = 0x0f 0x05 */
852 case 0x050f: currpers = 0; break;
853 /* i386: int 0x80 = 0xcd 0x80 */
854 case 0x80cd: currpers = 1; break;
855 default:
856 currpers = current_personality;
857 fprintf(stderr,
858 "Unknown syscall opcode (0x%04X) while "
859 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200860 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200861 break;
862 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100863# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000864 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100865#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000866# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200867 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000868 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200869 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200870 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200871 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000872 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200873 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000874 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200875 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100876#elif defined(ARM)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200877 /* Read complete register set in one go. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000878 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +0000879 return -1;
880
881 /*
882 * We only need to grab the syscall number on syscall entry.
883 */
884 if (regs.ARM_ip == 0) {
885 /*
886 * Note: we only deal with only 32-bit CPUs here.
887 */
888 if (regs.ARM_cpsr & 0x20) {
889 /*
890 * Get the Thumb-mode system call number
891 */
892 scno = regs.ARM_r7;
893 } else {
894 /*
895 * Get the ARM-mode system call number
896 */
897 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000898 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +0000899 if (errno)
900 return -1;
901
Roland McGrathf691bd22006-04-25 07:34:41 +0000902 /* Handle the EABI syscall convention. We do not
903 bother converting structures between the two
904 ABIs, but basic functionality should work even
905 if strace and the traced program have different
906 ABIs. */
907 if (scno == 0xef000000) {
908 scno = regs.ARM_r7;
909 } else {
910 if ((scno & 0x0ff00000) != 0x0f900000) {
911 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
912 scno);
913 return -1;
914 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000915
Roland McGrathf691bd22006-04-25 07:34:41 +0000916 /*
917 * Fixup the syscall number
918 */
919 scno &= 0x000fffff;
920 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000921 }
Roland McGrath56703312008-05-20 01:35:55 +0000922 if (scno & 0x0f0000) {
923 /*
924 * Handle ARM specific syscall
925 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000926 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +0000927 scno &= 0x0000ffff;
928 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000929 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +0000930
Roland McGrath0f87c492003-06-03 23:29:04 +0000931 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200932 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
933 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000934 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100935#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000936 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000937 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100938#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +0000939 unsigned long long regs[38];
940
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200941 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +0000942 return -1;
943 a3 = regs[REG_A3];
944 r2 = regs[REG_V0];
945
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200946 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200947 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200948 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100949 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200950 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000951 return 0;
952 }
Roland McGrath542c2c62008-05-20 01:11:56 +0000953 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100954#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000955 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000956 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200957 if (upeek(tcp, REG_V0, &scno) < 0)
958 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000959
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200960 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200961 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100962 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200963 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000964 return 0;
965 }
Wichert Akkermanf90da011999-10-31 21:15:38 +0000966 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100967#elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000968 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000969 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200970 if (upeek(tcp, REG_R0, &scno) < 0)
971 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000972
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200973 /*
974 * Do some sanity checks to figure out if it's
975 * really a syscall entry
976 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200977 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200978 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100979 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200980 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000981 return 0;
982 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000983 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100984#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000985 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000986 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000987 return -1;
988
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200989 /* Disassemble the syscall trap. */
990 /* Retrieve the syscall trap instruction. */
991 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100992# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200993 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
994 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100995# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200996 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100997# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200998 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +0000999 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001000
1001 /* Disassemble the trap to see what personality to use. */
1002 switch (trap) {
1003 case 0x91d02010:
1004 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001005 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001006 break;
1007 case 0x91d0206d:
1008 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001009 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001010 break;
1011 case 0x91d02000:
1012 /* SunOS syscall trap. (pers 1) */
1013 fprintf(stderr, "syscall: SunOS no support\n");
1014 return -1;
1015 case 0x91d02008:
1016 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001017 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001018 break;
1019 case 0x91d02009:
1020 /* NetBSD/FreeBSD syscall trap. */
1021 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1022 return -1;
1023 case 0x91d02027:
1024 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001025 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001026 break;
1027 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001028# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001029 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001030# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001031 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001032# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001033 return -1;
1034 }
1035
1036 /* Extract the system call number from the registers. */
1037 if (trap == 0x91d02027)
1038 scno = 156;
1039 else
1040 scno = regs.u_regs[U_REG_G1];
1041 if (scno == 0) {
1042 scno = regs.u_regs[U_REG_O0];
1043 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1044 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001045#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001046 if (upeek(tcp, PT_GR20, &scno) < 0)
1047 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001048#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001049 /*
1050 * In the new syscall ABI, the system call number is in R3.
1051 */
1052 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1053 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001054
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001055 if (scno < 0) {
1056 /* Odd as it may seem, a glibc bug has been known to cause
1057 glibc to issue bogus negative syscall numbers. So for
1058 our purposes, make strace print what it *should* have been */
1059 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001060 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001061 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001062 "Detected glibc bug: bogus system call"
1063 " number = %ld, correcting to %ld\n",
1064 scno,
1065 correct_scno);
1066 scno = correct_scno;
1067 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001068#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001069 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001070 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001071 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001072#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001073 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1074 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001075#elif defined(TILE)
Chris Metcalfc8c66982009-12-28 10:00:15 -05001076 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1077 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001078#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001079 if (upeek(tcp, 0, &scno) < 0)
1080 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001081#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001082
Denys Vlasenko523635f2012-02-25 02:44:25 +01001083#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001084 /* new syscall ABI returns result in R0 */
1085 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1086 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001087#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001088 /* ABI defines result returned in r9 */
1089 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1090 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001091#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001092
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001093 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001094 return 1;
1095}
1096
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001097/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001098 * Returns:
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001099 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
Roland McGratheb9e2e82009-06-02 16:49:22 -07001100 * 1: ok, continue in trace_syscall().
1101 * other: error, trace_syscall() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001102 * ("????" etc) and bail out.
1103 */
Roland McGratha4d48532005-06-08 20:45:28 +00001104static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001105syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001106{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001107 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001108#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001109 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001110 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001111 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1112 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001113 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001114#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001115 {
1116 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001117 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001118 rax = (int)rax; /* sign extend from 32 bits */
1119 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001120 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001121 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1122 return 0;
1123 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001124 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001125#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001126 /* TODO: we already fetched PT_GPR2 in get_scno
1127 * and stored it in syscall_mode, reuse it here
1128 * instead of re-fetching?
1129 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001130 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001131 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001132 if (syscall_mode != -ENOSYS)
1133 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001134 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001135 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001136 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001137 return 0;
1138 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001139#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001140 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001141 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001142 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001143 if (d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001144 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001145 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001146 return 0;
1147 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001148#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001149 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001150 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001151 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001152 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001153 if (ia32 && r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001154 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001155 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001156 return 0;
1157 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001158#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001159 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001160 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001161 if (r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001162 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001163 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001164 return 0;
1165 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001166#elif defined(MICROBLAZE)
1167 if (upeek(tcp, 3 * 4, &r3) < 0)
1168 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001169 if (r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001170 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001171 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001172 return 0;
1173 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001174#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001175 return 1;
1176}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001177
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001178static int
1179internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001180{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001181 /*
1182 * We must always trace a few critical system calls in order to
1183 * correctly support following forks in the presence of tracing
1184 * qualifiers.
1185 */
1186 int (*func)();
1187
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001188 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001189 return 0;
1190
1191 func = sysent[tcp->scno].sys_func;
1192
1193 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001194 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001195 || sys_clone == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001196 )
1197 return internal_fork(tcp);
1198
Denys Vlasenko84703742012-02-25 02:38:52 +01001199#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001200 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001201# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001202 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001203# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001204 )
1205 return internal_exec(tcp);
Roland McGrathc1e45922008-05-27 23:18:29 +00001206#endif
1207
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001208 return 0;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001209}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001210
Roland McGratha4d48532005-06-08 20:45:28 +00001211static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001212syscall_enter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001213{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001214 int i, nargs;
1215
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001216 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001217 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001218 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001219 nargs = tcp->u_nargs = MAX_ARGS;
1220
Denys Vlasenko523635f2012-02-25 02:44:25 +01001221#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001222 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001223 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1224 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001225#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001226 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001227 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1228 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001229#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001230 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001231 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001232 long rbs_end;
1233 /* be backwards compatible with kernel < 2.4.4... */
1234# ifndef PT_RBS_END
1235# define PT_RBS_END PT_AR_BSP
1236# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001237
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001238 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1239 return -1;
1240 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001241 return -1;
1242
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001243 sof = (cfm >> 0) & 0x7f;
1244 sol = (cfm >> 7) & 0x7f;
1245 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1246
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001247 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001248 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1249 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1250 return -1;
1251 }
1252 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001253 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1254 PT_R9 /* ECX = out1 */,
1255 PT_R10 /* EDX = out2 */,
1256 PT_R14 /* ESI = out3 */,
1257 PT_R15 /* EDI = out4 */,
1258 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001259
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001260 for (i = 0; i < nargs; ++i) {
1261 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1262 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001263 /* truncate away IVE sign-extension */
1264 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001265 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001266 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001267#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001268 /* N32 and N64 both use up to six registers. */
1269 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001270
1271 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1272 return -1;
1273
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001274 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001275 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001276# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001277 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001278# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001279 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001280#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001281 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001282 long sp;
1283
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001284 if (upeek(tcp, REG_SP, &sp) < 0)
1285 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001286 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001287 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1288 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001289 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001290 (char *)(tcp->u_arg + 4));
1291 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001292 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001293 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001294 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001295 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001296#elif defined(POWERPC)
1297# ifndef PT_ORIG_R3
1298# define PT_ORIG_R3 34
1299# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001300 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001301 if (upeek(tcp, (i==0) ?
1302 (sizeof(unsigned long) * PT_ORIG_R3) :
1303 ((i+PT_R3) * sizeof(unsigned long)),
1304 &tcp->u_arg[i]) < 0)
1305 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001306 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001307#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001308 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001309 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001310#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001311 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001312 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1313 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001314#elif defined(ARM)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001315 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001316 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001317#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001318 (void)i;
1319 (void)nargs;
1320 tcp->u_arg[0] = regs.r12;
1321 tcp->u_arg[1] = regs.r11;
1322 tcp->u_arg[2] = regs.r10;
1323 tcp->u_arg[3] = regs.r9;
1324 tcp->u_arg[4] = regs.r5;
1325 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001326#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001327 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 +02001328
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001329 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001330 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1331 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001332#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001333 static const int syscall_regs[MAX_ARGS] = {
1334 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1335 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001336 };
1337
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001338 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001339 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001340 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001341#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001342 int i;
1343 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001344 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001345
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001346 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001347 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1348 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001349#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001350 (void)i;
1351 (void)nargs;
1352 if (current_personality == 0) { /* x86-64 ABI */
1353 tcp->u_arg[0] = x86_64_regs.rdi;
1354 tcp->u_arg[1] = x86_64_regs.rsi;
1355 tcp->u_arg[2] = x86_64_regs.rdx;
1356 tcp->u_arg[3] = x86_64_regs.r10;
1357 tcp->u_arg[4] = x86_64_regs.r8;
1358 tcp->u_arg[5] = x86_64_regs.r9;
1359 } else { /* i386 ABI */
1360 /* Sign-extend lower 32 bits */
1361 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1362 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1363 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1364 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1365 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1366 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1367 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001368#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001369 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001370 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1371 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001372#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001373 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001374 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001375 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001376 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001377
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001378 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001379 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1380 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001381#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001382 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001383 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1384 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001385#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001386 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001387 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1388 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001389#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001390 (void)i;
1391 (void)nargs;
1392 tcp->u_arg[0] = i386_regs.ebx;
1393 tcp->u_arg[1] = i386_regs.ecx;
1394 tcp->u_arg[2] = i386_regs.edx;
1395 tcp->u_arg[3] = i386_regs.esi;
1396 tcp->u_arg[4] = i386_regs.edi;
1397 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001398#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001399 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001400 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1401 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001402#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001403 return 1;
1404}
1405
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001406static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001407trace_syscall_entering(struct tcb *tcp)
1408{
1409 int res, scno_good;
1410
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001411#if defined TCB_WAITEXECVE
1412 if (tcp->flags & TCB_WAITEXECVE) {
1413 /* This is the post-execve SIGTRAP. */
1414 tcp->flags &= ~TCB_WAITEXECVE;
1415 return 0;
1416 }
1417#endif
1418
Denys Vlasenko06602d92011-08-24 17:53:52 +02001419 scno_good = res = get_scno(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001420 if (res == 0)
1421 return res;
1422 if (res == 1)
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001423 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001424 if (res == 0)
1425 return res;
1426 if (res == 1)
1427 res = syscall_enter(tcp);
1428 if (res == 0)
1429 return res;
1430
1431 if (res != 1) {
1432 printleader(tcp);
1433 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001434 if (scno_good != 1)
1435 tprintf("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001436 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001437 tprintf("syscall_%lu(", tcp->scno);
1438 else
1439 tprintf("%s(", sysent[tcp->scno].sys_name);
1440 /*
1441 * " <unavailable>" will be added later by the code which
1442 * detects ptrace errors.
1443 */
1444 goto ret;
1445 }
1446
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001447#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1448 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001449# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001450 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001451 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001452 break;
1453 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001454# endif
1455# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001456 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001457 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001458 break;
1459 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001460# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001461 break;
1462 }
1463#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1464
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001465 internal_syscall(tcp);
1466
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001467 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001468 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1469 (tracing_paths && !pathtrace_match(tcp))) {
1470 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1471 return 0;
1472 }
1473
1474 tcp->flags &= ~TCB_FILTERED;
1475
1476 if (cflag == CFLAG_ONLY_STATS) {
1477 res = 0;
1478 goto ret;
1479 }
1480
1481 printleader(tcp);
1482 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001483 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001484 tprintf("syscall_%lu(", tcp->scno);
1485 else
1486 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001487 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001488 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1489 sysent[tcp->scno].sys_func != sys_exit))
1490 res = printargs(tcp);
1491 else
1492 res = (*sysent[tcp->scno].sys_func)(tcp);
1493
1494 if (fflush(tcp->outf) == EOF)
1495 return -1;
1496 ret:
1497 tcp->flags |= TCB_INSYSCALL;
1498 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001499 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001500 gettimeofday(&tcp->etime, NULL);
1501 return res;
1502}
1503
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001504/* Returns:
1505 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1506 * 1: ok, continue in trace_syscall().
1507 * other: error, trace_syscall() should print error indicator
1508 * ("????" etc) and bail out.
1509 */
1510static int
1511get_syscall_result(struct tcb *tcp)
1512{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001513#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001514 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1515 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001516#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001517# define SO_MASK 0x10000000
1518 {
1519 long flags;
1520 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1521 return -1;
1522 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &result) < 0)
1523 return -1;
1524 if (flags & SO_MASK)
1525 result = -result;
1526 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001527#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001528 /* Read complete register set in one go. */
1529 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1530 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001531#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001532 if (upeek(tcp, PT_R0, &r0) < 0)
1533 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001534#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001535 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001536 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001537#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001538 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001539 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001540#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001541# define IA64_PSR_IS ((long)1 << 34)
1542 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1543 ia32 = (psr & IA64_PSR_IS) != 0;
1544 if (upeek(tcp, PT_R8, &r8) < 0)
1545 return -1;
1546 if (upeek(tcp, PT_R10, &r10) < 0)
1547 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001548#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001549 /* Read complete register set in one go. */
1550 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1551 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001552#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001553 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1554 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001555#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001556 unsigned long long regs[38];
1557
1558 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1559 return -1;
1560 a3 = regs[REG_A3];
1561 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001562#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001563 if (upeek(tcp, REG_A3, &a3) < 0)
1564 return -1;
1565 if (upeek(tcp, REG_V0, &r2) < 0)
1566 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001567#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001568 if (upeek(tcp, REG_A3, &a3) < 0)
1569 return -1;
1570 if (upeek(tcp, REG_R0, &r0) < 0)
1571 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001572#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001573 /* Everything we need is in the current register set. */
1574 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1575 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001576#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001577 if (upeek(tcp, PT_GR28, &r28) < 0)
1578 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001579#elif defined(SH)
1580#elif defined(SH64)
1581#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001582 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1583 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001584#elif defined(TILE)
1585#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001586 if (upeek(tcp, 3 * 4, &r3) < 0)
1587 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001588#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001589
Denys Vlasenko523635f2012-02-25 02:44:25 +01001590#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001591 /* new syscall ABI returns result in R0 */
1592 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1593 return -1;
1594#elif defined(SH64)
1595 /* ABI defines result returned in r9 */
1596 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1597 return -1;
1598#endif
1599
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001600 return 1;
1601}
1602
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001603/* Called at each syscall exit.
1604 * Returns:
1605 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1606 * 1: ok, continue in trace_syscall().
1607 * other: error, trace_syscall() should print error indicator
1608 * ("????" etc) and bail out.
1609 */
1610static int
1611syscall_fixup_on_sysexit(struct tcb *tcp)
1612{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001613#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001614 if (syscall_mode != -ENOSYS)
1615 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001616 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001617 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1618 /*
1619 * Return from execve.
1620 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1621 * flag set for the post-execve SIGTRAP to see and reset.
1622 */
1623 gpr2 = 0;
1624 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001625#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001626 return 1;
1627}
1628
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001629/*
1630 * Check the syscall return value register value for whether it is
1631 * a negated errno code indicating an error, or a success return value.
1632 */
1633static inline int
1634is_negated_errno(unsigned long int val)
1635{
1636 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001637#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001638 if (personality_wordsize[current_personality] < sizeof(val)) {
1639 val = (unsigned int) val;
1640 max = (unsigned int) max;
1641 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001642#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001643 return val > max;
1644}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001645
1646static int
1647get_error(struct tcb *tcp)
1648{
1649 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001650 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001651 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001652 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1653 check_errno = 0;
1654 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001655#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001656 if (check_errno && is_negated_errno(gpr2)) {
1657 tcp->u_rval = -1;
1658 u_error = -gpr2;
1659 }
1660 else {
1661 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001662 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001663#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001664 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001665 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001666 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001667 }
1668 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001669 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001670 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001671#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001672 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001673 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001674 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001675 }
1676 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001677 tcp->u_rval = x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001678 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001679#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001680 if (ia32) {
1681 int err;
1682
1683 err = (int)r8;
1684 if (check_errno && is_negated_errno(err)) {
1685 tcp->u_rval = -1;
1686 u_error = -err;
1687 }
1688 else {
1689 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001690 }
1691 } else {
1692 if (check_errno && r10) {
1693 tcp->u_rval = -1;
1694 u_error = r8;
1695 } else {
1696 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001697 }
1698 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001699#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001700 if (check_errno && a3) {
1701 tcp->u_rval = -1;
1702 u_error = r2;
1703 } else {
1704 tcp->u_rval = r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001705 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001706#elif defined(POWERPC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001707 if (check_errno && is_negated_errno(result)) {
1708 tcp->u_rval = -1;
1709 u_error = -result;
1710 }
1711 else {
1712 tcp->u_rval = result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001713 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001714#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001715 if (check_errno && is_negated_errno(d0)) {
1716 tcp->u_rval = -1;
1717 u_error = -d0;
1718 }
1719 else {
1720 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001721 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001722#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001723 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1724 tcp->u_rval = -1;
1725 u_error = -regs.ARM_r0;
1726 }
1727 else {
1728 tcp->u_rval = regs.ARM_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001729 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001730#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001731 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1732 tcp->u_rval = -1;
1733 u_error = -regs.r12;
1734 }
1735 else {
1736 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001737 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001738#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001739 if (check_errno && is_negated_errno(r0)) {
1740 tcp->u_rval = -1;
1741 u_error = -r0;
1742 } else {
1743 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001744 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001745#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001746 if (check_errno && a3) {
1747 tcp->u_rval = -1;
1748 u_error = r0;
1749 }
1750 else {
1751 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001752 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001753#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001754 if (check_errno && regs.psr & PSR_C) {
1755 tcp->u_rval = -1;
1756 u_error = regs.u_regs[U_REG_O0];
1757 }
1758 else {
1759 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001760 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001761#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001762 if (check_errno && regs.tstate & 0x1100000000UL) {
1763 tcp->u_rval = -1;
1764 u_error = regs.u_regs[U_REG_O0];
1765 }
1766 else {
1767 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001768 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001769#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001770 if (check_errno && is_negated_errno(r28)) {
1771 tcp->u_rval = -1;
1772 u_error = -r28;
1773 }
1774 else {
1775 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001776 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001777#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001778 if (check_errno && is_negated_errno(r0)) {
1779 tcp->u_rval = -1;
1780 u_error = -r0;
1781 }
1782 else {
1783 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001784 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001785#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001786 if (check_errno && is_negated_errno(r9)) {
1787 tcp->u_rval = -1;
1788 u_error = -r9;
1789 }
1790 else {
1791 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001792 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001793#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001794 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1795 tcp->u_rval = -1;
1796 u_error = -r10;
1797 }
1798 else {
1799 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001800 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001801#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001802 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001803 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1804 return -1;
1805 if (check_errno && rval < 0 && rval > -nerrnos) {
1806 tcp->u_rval = -1;
1807 u_error = -rval;
1808 }
1809 else {
1810 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001811 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001812#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001813 if (check_errno && is_negated_errno(r3)) {
1814 tcp->u_rval = -1;
1815 u_error = -r3;
1816 }
1817 else {
1818 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001819 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001820#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001821 tcp->u_error = u_error;
1822 return 1;
1823}
1824
1825static void
1826dumpio(struct tcb *tcp)
1827{
1828 if (syserror(tcp))
1829 return;
1830 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1831 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001832 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001833 return;
1834 if (sysent[tcp->scno].sys_func == printargs)
1835 return;
1836 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1837 if (sysent[tcp->scno].sys_func == sys_read ||
1838 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001839 sysent[tcp->scno].sys_func == sys_recv ||
1840 sysent[tcp->scno].sys_func == sys_recvfrom)
1841 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1842 else if (sysent[tcp->scno].sys_func == sys_readv)
1843 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1844 return;
1845 }
1846 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1847 if (sysent[tcp->scno].sys_func == sys_write ||
1848 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001849 sysent[tcp->scno].sys_func == sys_send ||
1850 sysent[tcp->scno].sys_func == sys_sendto)
1851 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1852 else if (sysent[tcp->scno].sys_func == sys_writev)
1853 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1854 return;
1855 }
1856}
1857
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001858static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001859trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001860{
1861 int sys_res;
1862 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001863 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001864 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001865
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001866 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001867 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001868 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001869
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001870#if SUPPORTED_PERSONALITIES > 1
1871 update_personality(tcp, tcp->currpers);
1872#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001873 res = get_syscall_result(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001874 if (res == 0)
1875 return res;
1876 if (res == 1)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001877 res = syscall_fixup_on_sysexit(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001878 if (res == 0)
1879 return res;
1880 if (res == 1)
1881 res = get_error(tcp);
1882 if (res == 0)
1883 return res;
1884 if (res == 1)
1885 internal_syscall(tcp);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001886
Grant Edwards8a082772011-04-07 20:25:40 +00001887 if (res == 1 && filtered(tcp)) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001888 goto ret;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001889 }
1890
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001891 /* TODO: TCB_REPRINT is probably not necessary:
1892 * we can determine whether reprinting is needed
1893 * by examining printing_tcp. Something like:
1894 * if not in -ff mode, and printing_tcp != tcp,
1895 * then the log is not currenlty ends with *our*
1896 * syscall entry output, but with something else,
1897 * and we need to reprint.
1898 * If we'd implement this, printing_tcp = tcp
1899 * assignments in code below can be made more logical.
1900 */
1901
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001902 if (tcp->flags & TCB_REPRINT) {
1903 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001904 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001905 tprintf("<... syscall_%lu resumed> ", tcp->scno);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001906 else
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001907 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001908 }
1909
1910 if (cflag) {
1911 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02001912 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02001913 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001914 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001915 }
1916 }
1917
1918 if (res != 1) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001919 printing_tcp = tcp;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001920 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001921 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01001922 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001923 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001924 tcp->flags &= ~TCB_INSYSCALL;
1925 return res;
1926 }
1927
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001928 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001929 || (qual_flags[tcp->scno] & QUAL_RAW)) {
1930 printing_tcp = tcp;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001931 sys_res = printargs(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001932 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001933 /* FIXME: not_failing_only (IOW, option -z) is broken:
1934 * failure of syscall is known only after syscall return.
1935 * Thus we end up with something like this on, say, ENOENT:
1936 * open("doesnt_exist", O_RDONLY <unfinished ...>
1937 * {next syscall decode}
1938 * whereas the intended result is that open(...) line
1939 * is not shown at all.
1940 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001941 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02001942 goto ret; /* ignore failed syscalls */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001943 printing_tcp = tcp;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001944 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
1945 }
1946
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001947 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001948 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02001949 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001950 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001951 qual_flags[tcp->scno] & QUAL_RAW) {
1952 if (u_error)
1953 tprintf("= -1 (errno %ld)", u_error);
1954 else
1955 tprintf("= %#lx", tcp->u_rval);
1956 }
1957 else if (!(sys_res & RVAL_NONE) && u_error) {
1958 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01001959 /* Blocked signals do not interrupt any syscalls.
1960 * In this case syscalls don't return ERESTARTfoo codes.
1961 *
1962 * Deadly signals set to SIG_DFL interrupt syscalls
1963 * and kill the process regardless of which of the codes below
1964 * is returned by the interrupted syscall.
1965 * In some cases, kernel forces a kernel-generated deadly
1966 * signal to be unblocked and set to SIG_DFL (and thus cause
1967 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
1968 * or SIGILL. (The alternative is to leave process spinning
1969 * forever on the faulty instruction - not useful).
1970 *
1971 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
1972 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
1973 * but kernel will always restart them.
1974 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001975 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01001976 /* Most common type of signal-interrupted syscall exit code.
1977 * The system call will be restarted with the same arguments
1978 * if SA_RESTART is set; otherwise, it will fail with EINTR.
1979 */
1980 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001981 break;
1982 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01001983 /* Rare. For example, fork() returns this if interrupted.
1984 * SA_RESTART is ignored (assumed set): the restart is unconditional.
1985 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001986 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001987 break;
1988 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01001989 /* pause(), rt_sigsuspend() etc use this code.
1990 * SA_RESTART is ignored (assumed not set):
1991 * syscall won't restart (will return EINTR instead)
1992 * even after signal with SA_RESTART set.
1993 * However, after SIG_IGN or SIG_DFL signal it will.
1994 */
1995 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001996 break;
1997 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01001998 /* Syscalls like nanosleep(), poll() which can't be
1999 * restarted with their original arguments use this
2000 * code. Kernel will execute restart_syscall() instead,
2001 * which changes arguments before restarting syscall.
2002 * SA_RESTART is ignored (assumed not set) similarly
2003 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2004 * since restart data is saved in "restart block"
2005 * in task struct, and if signal handler uses a syscall
2006 * which in turn saves another such restart block,
2007 * old data is lost and restart becomes impossible)
2008 */
2009 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002010 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002011 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002012 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002013 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002014 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002015 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002016 strerror(u_error));
2017 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002018 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002019 strerror(u_error));
2020 break;
2021 }
2022 if ((sys_res & RVAL_STR) && tcp->auxstr)
2023 tprintf(" (%s)", tcp->auxstr);
2024 }
2025 else {
2026 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002027 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002028 else {
2029 switch (sys_res & RVAL_MASK) {
2030 case RVAL_HEX:
2031 tprintf("= %#lx", tcp->u_rval);
2032 break;
2033 case RVAL_OCTAL:
2034 tprintf("= %#lo", tcp->u_rval);
2035 break;
2036 case RVAL_UDECIMAL:
2037 tprintf("= %lu", tcp->u_rval);
2038 break;
2039 case RVAL_DECIMAL:
2040 tprintf("= %ld", tcp->u_rval);
2041 break;
2042#ifdef HAVE_LONG_LONG
2043 case RVAL_LHEX:
2044 tprintf("= %#llx", tcp->u_lrval);
2045 break;
2046 case RVAL_LOCTAL:
2047 tprintf("= %#llo", tcp->u_lrval);
2048 break;
2049 case RVAL_LUDECIMAL:
2050 tprintf("= %llu", tcp->u_lrval);
2051 break;
2052 case RVAL_LDECIMAL:
2053 tprintf("= %lld", tcp->u_lrval);
2054 break;
2055#endif
2056 default:
2057 fprintf(stderr,
2058 "invalid rval format\n");
2059 break;
2060 }
2061 }
2062 if ((sys_res & RVAL_STR) && tcp->auxstr)
2063 tprintf(" (%s)", tcp->auxstr);
2064 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002065 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002066 tv_sub(&tv, &tv, &tcp->etime);
2067 tprintf(" <%ld.%06ld>",
2068 (long) tv.tv_sec, (long) tv.tv_usec);
2069 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002070 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002071 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002072 line_ended();
2073
Denys Vlasenko3b738812011-08-22 02:06:35 +02002074 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002075 tcp->flags &= ~TCB_INSYSCALL;
2076 return 0;
2077}
2078
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002079int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002080trace_syscall(struct tcb *tcp)
2081{
2082 return exiting(tcp) ?
2083 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2084}