blob: 657cdbf151fd1cca60e9d4a7e3358fbb3984ddc9 [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
Wichert Akkerman8829a551999-06-11 13:18:40 +0000517enum subcall_style { shift_style, deref_style, mask_style, door_style };
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000518
Mike Frysinger3362e892012-03-15 01:09:19 -0400519#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000520
Roland McGratha4d48532005-06-08 20:45:28 +0000521static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200522decode_subcall(struct tcb *tcp, int subcall, int nsubcalls, enum subcall_style style)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000523{
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000524 unsigned long addr, mask;
Denys Vlasenko4b887a52011-08-23 13:32:38 +0200525 int i, n;
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000526 int size = personality_wordsize[current_personality];
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000527
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000528 switch (style) {
529 case shift_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000530 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
531 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000532 tcp->scno = subcall + tcp->u_arg[0];
Denys Vlasenko4b887a52011-08-23 13:32:38 +0200533 tcp->u_nargs = n = sysent[tcp->scno].nargs;
534 for (i = 0; i < n; i++)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000535 tcp->u_arg[i] = tcp->u_arg[i + 1];
536 break;
537 case deref_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000538 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
539 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000540 tcp->scno = subcall + tcp->u_arg[0];
541 addr = tcp->u_arg[1];
Denys Vlasenko4b887a52011-08-23 13:32:38 +0200542 tcp->u_nargs = n = sysent[tcp->scno].nargs;
543 for (i = 0; i < n; i++) {
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000544 if (size == sizeof(int)) {
545 unsigned int arg;
546 if (umove(tcp, addr, &arg) < 0)
547 arg = 0;
548 tcp->u_arg[i] = arg;
549 }
550 else if (size == sizeof(long)) {
551 unsigned long arg;
552 if (umove(tcp, addr, &arg) < 0)
553 arg = 0;
554 tcp->u_arg[i] = arg;
555 }
556 else
557 abort();
558 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000559 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000560 break;
561 case mask_style:
562 mask = (tcp->u_arg[0] >> 8) & 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000563 for (i = 0; mask; i++)
564 mask >>= 1;
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000565 if (i >= nsubcalls)
566 return;
567 tcp->u_arg[0] &= 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000568 tcp->scno = subcall + i;
Denys Vlasenkoafc64032011-08-23 13:29:01 +0200569 tcp->u_nargs = sysent[tcp->scno].nargs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000570 break;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000571 case door_style:
572 /*
573 * Oh, yuck. The call code is the *sixth* argument.
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000574 * (don't you mean the *last* argument? - JH)
Wichert Akkerman8829a551999-06-11 13:18:40 +0000575 */
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000576 if (tcp->u_arg[5] < 0 || tcp->u_arg[5] >= nsubcalls)
577 return;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000578 tcp->scno = subcall + tcp->u_arg[5];
Denys Vlasenkoafc64032011-08-23 13:29:01 +0200579 tcp->u_nargs = sysent[tcp->scno].nargs;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000580 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000581 }
582}
Mike Frysinger3362e892012-03-15 01:09:19 -0400583
584#endif /* SYS_socket_subcall || SYS_ipc_subcall */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000585
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200586int
587printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000588{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200589 if (entering(tcp)) {
590 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000591
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200592 for (i = 0; i < tcp->u_nargs; i++)
593 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
594 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000595 return 0;
596}
597
Denys Vlasenko72879c62012-02-27 14:18:02 +0100598int
599printargs_lu(struct tcb *tcp)
600{
601 if (entering(tcp)) {
602 int i;
603
604 for (i = 0; i < tcp->u_nargs; i++)
605 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
606 }
607 return 0;
608}
609
610int
611printargs_ld(struct tcb *tcp)
612{
613 if (entering(tcp)) {
614 int i;
615
616 for (i = 0; i < tcp->u_nargs; i++)
617 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
618 }
619 return 0;
620}
621
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200622long
623getrval2(struct tcb *tcp)
624{
625 long val = -1;
626
Denys Vlasenko523635f2012-02-25 02:44:25 +0100627#if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200628 struct pt_regs regs;
629 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
630 return -1;
631 val = regs.u_regs[U_REG_O1];
632#elif defined(SH)
633 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
634 return -1;
635#elif defined(IA64)
636 if (upeek(tcp, PT_R9, &val) < 0)
637 return -1;
638#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200639
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200640 return val;
641}
642
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200643int
644is_restart_error(struct tcb *tcp)
645{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200646 switch (tcp->u_error) {
647 case ERESTARTSYS:
648 case ERESTARTNOINTR:
649 case ERESTARTNOHAND:
650 case ERESTART_RESTARTBLOCK:
651 return 1;
652 default:
653 break;
654 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200655 return 0;
656}
657
Denys Vlasenko523635f2012-02-25 02:44:25 +0100658#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100659struct pt_regs i386_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100660#elif defined(X86_64)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100661/*
662 * On 32 bits, pt_regs and user_regs_struct are the same,
663 * but on 64 bits, user_regs_struct has six more fields:
664 * fs_base, gs_base, ds, es, fs, gs.
665 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
666 */
667static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100668#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200669long r8, r10, psr; /* TODO: make static? */
670long ia32 = 0; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100671#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +0200672static long result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100673#elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200674static long d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100675#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200676static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100677#elif defined(ARM)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200678static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100679#elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200680static long r0;
681static long a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100682#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200683static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100684#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200685static struct pt_regs regs;
686static unsigned long trap;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100687#elif defined(LINUX_MIPSN32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200688static long long a3;
689static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100690#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200691static long a3;
692static long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100693#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200694static long gpr2;
695static long pc;
696static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100697#elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200698static long r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100699#elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200700static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100701#elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200702static long r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100703#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200704static long r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100705#elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200706static long r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100707#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000708
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200709/* Returns:
710 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
711 * 1: ok, continue in trace_syscall().
712 * other: error, trace_syscall() should print error indicator
713 * ("????" etc) and bail out.
714 */
Denys Vlasenko9a36ae52011-08-24 16:47:32 +0200715static
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000716int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200717get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000718{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000719 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000720
Denys Vlasenko523635f2012-02-25 02:44:25 +0100721#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000722 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200723 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000724
725 if (syscall_mode != -ENOSYS) {
726 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000727 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000728 */
729 scno = syscall_mode;
730 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000731 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000732 * Old style of "passing" the scno via the SVC instruction.
733 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000734 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200735 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200736 static const int gpr_offset[16] = {
737 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
738 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
739 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
740 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
741 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000742
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000743 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000744 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000745 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000746 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000747 if (errno) {
748 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000749 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000750 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000751
752 /*
753 * We have to check if the SVC got executed directly or via an
754 * EXECUTE instruction. In case of EXECUTE it is necessary to do
755 * instruction decoding to derive the system call number.
756 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
757 * so that this doesn't work if a SVC opcode is part of an EXECUTE
758 * opcode. Since there is no way to find out the opcode size this
759 * is the best we can do...
760 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000761 if ((opcode & 0xff00) == 0x0a00) {
762 /* SVC opcode */
763 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000764 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000765 else {
766 /* SVC got executed by EXECUTE instruction */
767
768 /*
769 * Do instruction decoding of EXECUTE. If you really want to
770 * understand this, read the Principles of Operations.
771 */
772 svc_addr = (void *) (opcode & 0xfff);
773
774 tmp = 0;
775 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000776 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000777 return -1;
778 svc_addr += tmp;
779
780 tmp = 0;
781 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000782 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000783 return -1;
784 svc_addr += tmp;
785
Denys Vlasenkofb036672009-01-23 16:30:26 +0000786 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000787 if (errno)
788 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100789# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000790 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100791# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000792 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100793# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000794 tmp = 0;
795 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000796 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000797 return -1;
798
799 scno = (scno | tmp) & 0xff;
800 }
801 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100802#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000803 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000804 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100805# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200806 /* TODO: speed up strace by not doing this at every syscall.
807 * We only need to do it after execve.
808 */
809 int currpers;
810 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200811
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200812 /* Check for 64/32 bit mode. */
813 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
814 return -1;
815 /* SF is bit 0 of MSR */
816 if (val < 0)
817 currpers = 0;
818 else
819 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000820 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100821# endif
822#elif defined(AVR32)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200823 /* Read complete register set in one go. */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000824 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
825 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200826 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100827#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000828 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000829 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100830#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200831 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000832 return -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200833 scno = i386_regs.orig_eax;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100834#elif defined(X86_64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200835 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200836 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
837 return -1;
838 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +0000839
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200840 /* Check CS register value. On x86-64 linux it is:
841 * 0x33 for long mode (64 bit)
842 * 0x23 for compatibility mode (32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200843 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200844 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200845 case 0x23: currpers = 1; break;
846 case 0x33: currpers = 0; break;
847 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200848 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200849 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200850 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200851 currpers = current_personality;
852 break;
853 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100854# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200855 /* This version analyzes the opcode of a syscall instruction.
856 * (int 0x80 on i386 vs. syscall on x86-64)
857 * It works, but is too complicated.
858 */
859 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +0000860
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200861 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +0000862
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200863 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
864 rip -= 2;
865 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +0000866
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200867 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200868 if (errno)
869 fprintf(stderr, "ptrace_peektext failed: %s\n",
870 strerror(errno));
871 switch (call & 0xffff) {
872 /* x86-64: syscall = 0x0f 0x05 */
873 case 0x050f: currpers = 0; break;
874 /* i386: int 0x80 = 0xcd 0x80 */
875 case 0x80cd: currpers = 1; break;
876 default:
877 currpers = current_personality;
878 fprintf(stderr,
879 "Unknown syscall opcode (0x%04X) while "
880 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200881 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200882 break;
883 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100884# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000885 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100886#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000887# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200888 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000889 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200890 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200891 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200892 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000893 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200894 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000895 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200896 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100897#elif defined(ARM)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200898 /* Read complete register set in one go. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000899 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +0000900 return -1;
901
902 /*
903 * We only need to grab the syscall number on syscall entry.
904 */
905 if (regs.ARM_ip == 0) {
906 /*
907 * Note: we only deal with only 32-bit CPUs here.
908 */
909 if (regs.ARM_cpsr & 0x20) {
910 /*
911 * Get the Thumb-mode system call number
912 */
913 scno = regs.ARM_r7;
914 } else {
915 /*
916 * Get the ARM-mode system call number
917 */
918 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000919 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +0000920 if (errno)
921 return -1;
922
Roland McGrathf691bd22006-04-25 07:34:41 +0000923 /* Handle the EABI syscall convention. We do not
924 bother converting structures between the two
925 ABIs, but basic functionality should work even
926 if strace and the traced program have different
927 ABIs. */
928 if (scno == 0xef000000) {
929 scno = regs.ARM_r7;
930 } else {
931 if ((scno & 0x0ff00000) != 0x0f900000) {
932 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
933 scno);
934 return -1;
935 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000936
Roland McGrathf691bd22006-04-25 07:34:41 +0000937 /*
938 * Fixup the syscall number
939 */
940 scno &= 0x000fffff;
941 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000942 }
Roland McGrath56703312008-05-20 01:35:55 +0000943 if (scno & 0x0f0000) {
944 /*
945 * Handle ARM specific syscall
946 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000947 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +0000948 scno &= 0x0000ffff;
949 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000950 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +0000951
Roland McGrath0f87c492003-06-03 23:29:04 +0000952 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200953 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
954 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000955 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100956#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000957 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100959#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +0000960 unsigned long long regs[38];
961
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200962 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +0000963 return -1;
964 a3 = regs[REG_A3];
965 r2 = regs[REG_V0];
966
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200967 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200968 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200969 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100970 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200971 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000972 return 0;
973 }
Roland McGrath542c2c62008-05-20 01:11:56 +0000974 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100975#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000976 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000977 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200978 if (upeek(tcp, REG_V0, &scno) < 0)
979 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000980
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200981 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200982 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100983 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200984 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000985 return 0;
986 }
Wichert Akkermanf90da011999-10-31 21:15:38 +0000987 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100988#elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000989 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000990 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200991 if (upeek(tcp, REG_R0, &scno) < 0)
992 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000993
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200994 /*
995 * Do some sanity checks to figure out if it's
996 * really a syscall entry
997 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200998 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200999 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001000 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001001 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001002 return 0;
1003 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001004 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001005#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001006 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001007 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001008 return -1;
1009
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001010 /* Disassemble the syscall trap. */
1011 /* Retrieve the syscall trap instruction. */
1012 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001013# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001014 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1015 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001016# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001017 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001018# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001019 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001020 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001021
1022 /* Disassemble the trap to see what personality to use. */
1023 switch (trap) {
1024 case 0x91d02010:
1025 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001026 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001027 break;
1028 case 0x91d0206d:
1029 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001030 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001031 break;
1032 case 0x91d02000:
1033 /* SunOS syscall trap. (pers 1) */
1034 fprintf(stderr, "syscall: SunOS no support\n");
1035 return -1;
1036 case 0x91d02008:
1037 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001038 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001039 break;
1040 case 0x91d02009:
1041 /* NetBSD/FreeBSD syscall trap. */
1042 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1043 return -1;
1044 case 0x91d02027:
1045 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001046 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001047 break;
1048 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001049# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001050 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001051# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001052 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001053# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001054 return -1;
1055 }
1056
1057 /* Extract the system call number from the registers. */
1058 if (trap == 0x91d02027)
1059 scno = 156;
1060 else
1061 scno = regs.u_regs[U_REG_G1];
1062 if (scno == 0) {
1063 scno = regs.u_regs[U_REG_O0];
1064 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1065 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001066#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001067 if (upeek(tcp, PT_GR20, &scno) < 0)
1068 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001069#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001070 /*
1071 * In the new syscall ABI, the system call number is in R3.
1072 */
1073 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1074 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001075
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001076 if (scno < 0) {
1077 /* Odd as it may seem, a glibc bug has been known to cause
1078 glibc to issue bogus negative syscall numbers. So for
1079 our purposes, make strace print what it *should* have been */
1080 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001081 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001082 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001083 "Detected glibc bug: bogus system call"
1084 " number = %ld, correcting to %ld\n",
1085 scno,
1086 correct_scno);
1087 scno = correct_scno;
1088 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001089#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001090 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001091 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001092 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001093#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001094 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1095 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001096#elif defined(TILE)
Chris Metcalfc8c66982009-12-28 10:00:15 -05001097 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1098 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001099#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001100 if (upeek(tcp, 0, &scno) < 0)
1101 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001102#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001103
Denys Vlasenko523635f2012-02-25 02:44:25 +01001104#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001105 /* new syscall ABI returns result in R0 */
1106 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1107 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001108#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001109 /* ABI defines result returned in r9 */
1110 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1111 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001112#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001113
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001114 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001115 return 1;
1116}
1117
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001118/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001119 * Returns:
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001120 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
Roland McGratheb9e2e82009-06-02 16:49:22 -07001121 * 1: ok, continue in trace_syscall().
1122 * other: error, trace_syscall() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001123 * ("????" etc) and bail out.
1124 */
Roland McGratha4d48532005-06-08 20:45:28 +00001125static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001126syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001127{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001128 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001129#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001130 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001131 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001132 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1133 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001134 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001135#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001136 {
1137 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001138 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001139 rax = (int)rax; /* sign extend from 32 bits */
1140 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001141 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001142 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1143 return 0;
1144 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001145 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001146#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001147 /* TODO: we already fetched PT_GPR2 in get_scno
1148 * and stored it in syscall_mode, reuse it here
1149 * instead of re-fetching?
1150 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001151 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001152 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001153 if (syscall_mode != -ENOSYS)
1154 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001155 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001156 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001157 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001158 return 0;
1159 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001160#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001161 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001162 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001164 if (d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001165 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001166 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001167 return 0;
1168 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001169#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001170 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001171 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001172 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001173 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001174 if (ia32 && r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001175 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001176 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001177 return 0;
1178 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001179#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001180 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001181 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001182 if (r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001183 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001184 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001185 return 0;
1186 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001187#elif defined(MICROBLAZE)
1188 if (upeek(tcp, 3 * 4, &r3) < 0)
1189 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001190 if (r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001191 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001192 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001193 return 0;
1194 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001195#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001196 return 1;
1197}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001198
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001199static int
1200internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001201{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001202 /*
1203 * We must always trace a few critical system calls in order to
1204 * correctly support following forks in the presence of tracing
1205 * qualifiers.
1206 */
1207 int (*func)();
1208
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001209 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001210 return 0;
1211
1212 func = sysent[tcp->scno].sys_func;
1213
1214 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001215 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001216 || sys_clone == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001217 )
1218 return internal_fork(tcp);
1219
Denys Vlasenko84703742012-02-25 02:38:52 +01001220#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001221 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001222# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001223 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001224# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001225 )
1226 return internal_exec(tcp);
Roland McGrathc1e45922008-05-27 23:18:29 +00001227#endif
1228
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001229 return 0;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001230}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001231
Roland McGratha4d48532005-06-08 20:45:28 +00001232static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001233syscall_enter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001234{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001235 int i, nargs;
1236
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001237 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001238 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001239 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001240 nargs = tcp->u_nargs = MAX_ARGS;
1241
Denys Vlasenko523635f2012-02-25 02:44:25 +01001242#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001243 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001244 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1245 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001246#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001247 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001248 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1249 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001250#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001251 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001252 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001253 long rbs_end;
1254 /* be backwards compatible with kernel < 2.4.4... */
1255# ifndef PT_RBS_END
1256# define PT_RBS_END PT_AR_BSP
1257# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001258
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001259 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1260 return -1;
1261 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001262 return -1;
1263
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001264 sof = (cfm >> 0) & 0x7f;
1265 sol = (cfm >> 7) & 0x7f;
1266 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1267
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001268 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001269 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1270 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1271 return -1;
1272 }
1273 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001274 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1275 PT_R9 /* ECX = out1 */,
1276 PT_R10 /* EDX = out2 */,
1277 PT_R14 /* ESI = out3 */,
1278 PT_R15 /* EDI = out4 */,
1279 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001280
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001281 for (i = 0; i < nargs; ++i) {
1282 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1283 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001284 /* truncate away IVE sign-extension */
1285 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001286 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001287 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001288#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001289 /* N32 and N64 both use up to six registers. */
1290 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001291
1292 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1293 return -1;
1294
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001295 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001296 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001297# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001298 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001299# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001300 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001301#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001302 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001303 long sp;
1304
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001305 if (upeek(tcp, REG_SP, &sp) < 0)
1306 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001307 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001308 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1309 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001310 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001311 (char *)(tcp->u_arg + 4));
1312 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001313 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001314 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001315 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001316 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001317#elif defined(POWERPC)
1318# ifndef PT_ORIG_R3
1319# define PT_ORIG_R3 34
1320# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001321 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001322 if (upeek(tcp, (i==0) ?
1323 (sizeof(unsigned long) * PT_ORIG_R3) :
1324 ((i+PT_R3) * sizeof(unsigned long)),
1325 &tcp->u_arg[i]) < 0)
1326 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001327 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001328#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001329 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001330 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001331#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001332 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001333 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1334 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001335#elif defined(ARM)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001336 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001337 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001338#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001339 (void)i;
1340 (void)nargs;
1341 tcp->u_arg[0] = regs.r12;
1342 tcp->u_arg[1] = regs.r11;
1343 tcp->u_arg[2] = regs.r10;
1344 tcp->u_arg[3] = regs.r9;
1345 tcp->u_arg[4] = regs.r5;
1346 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001347#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001348 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 +02001349
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001350 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001351 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1352 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001353#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001354 static const int syscall_regs[MAX_ARGS] = {
1355 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1356 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001357 };
1358
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001359 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001360 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001361 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001362#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001363 int i;
1364 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001365 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001366
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001367 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001368 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1369 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001370#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001371 (void)i;
1372 (void)nargs;
1373 if (current_personality == 0) { /* x86-64 ABI */
1374 tcp->u_arg[0] = x86_64_regs.rdi;
1375 tcp->u_arg[1] = x86_64_regs.rsi;
1376 tcp->u_arg[2] = x86_64_regs.rdx;
1377 tcp->u_arg[3] = x86_64_regs.r10;
1378 tcp->u_arg[4] = x86_64_regs.r8;
1379 tcp->u_arg[5] = x86_64_regs.r9;
1380 } else { /* i386 ABI */
1381 /* Sign-extend lower 32 bits */
1382 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1383 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1384 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1385 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1386 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1387 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1388 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001389#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001390 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001391 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1392 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001393#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001394 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001395 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001396 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001397 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001398
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, crisregs[i], &tcp->u_arg[i]) < 0)
1401 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001402#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001403 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001404 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1405 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001406#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001407 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001408 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1409 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001410#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001411 (void)i;
1412 (void)nargs;
1413 tcp->u_arg[0] = i386_regs.ebx;
1414 tcp->u_arg[1] = i386_regs.ecx;
1415 tcp->u_arg[2] = i386_regs.edx;
1416 tcp->u_arg[3] = i386_regs.esi;
1417 tcp->u_arg[4] = i386_regs.edi;
1418 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001419#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001420 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001421 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1422 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001423#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001424 return 1;
1425}
1426
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001427static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001428trace_syscall_entering(struct tcb *tcp)
1429{
1430 int res, scno_good;
1431
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001432#if defined TCB_WAITEXECVE
1433 if (tcp->flags & TCB_WAITEXECVE) {
1434 /* This is the post-execve SIGTRAP. */
1435 tcp->flags &= ~TCB_WAITEXECVE;
1436 return 0;
1437 }
1438#endif
1439
Denys Vlasenko06602d92011-08-24 17:53:52 +02001440 scno_good = res = get_scno(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001441 if (res == 0)
1442 return res;
1443 if (res == 1)
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001444 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001445 if (res == 0)
1446 return res;
1447 if (res == 1)
1448 res = syscall_enter(tcp);
1449 if (res == 0)
1450 return res;
1451
1452 if (res != 1) {
1453 printleader(tcp);
1454 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001455 if (scno_good != 1)
1456 tprintf("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001457 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001458 tprintf("syscall_%lu(", tcp->scno);
1459 else
1460 tprintf("%s(", sysent[tcp->scno].sys_name);
1461 /*
1462 * " <unavailable>" will be added later by the code which
1463 * detects ptrace errors.
1464 */
1465 goto ret;
1466 }
1467
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001468#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1469 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001470# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001471 if (sysent[tcp->scno].sys_func == sys_socketcall) {
1472 decode_subcall(tcp, SYS_socket_subcall,
1473 SYS_socket_nsubcalls, deref_style);
1474 break;
1475 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001476# endif
1477# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001478 if (sysent[tcp->scno].sys_func == sys_ipc) {
1479 decode_subcall(tcp, SYS_ipc_subcall,
1480 SYS_ipc_nsubcalls, shift_style);
1481 break;
1482 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001483# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001484 break;
1485 }
1486#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1487
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001488 internal_syscall(tcp);
1489
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001490 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001491 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1492 (tracing_paths && !pathtrace_match(tcp))) {
1493 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1494 return 0;
1495 }
1496
1497 tcp->flags &= ~TCB_FILTERED;
1498
1499 if (cflag == CFLAG_ONLY_STATS) {
1500 res = 0;
1501 goto ret;
1502 }
1503
1504 printleader(tcp);
1505 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001506 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001507 tprintf("syscall_%lu(", tcp->scno);
1508 else
1509 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001510 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001511 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1512 sysent[tcp->scno].sys_func != sys_exit))
1513 res = printargs(tcp);
1514 else
1515 res = (*sysent[tcp->scno].sys_func)(tcp);
1516
1517 if (fflush(tcp->outf) == EOF)
1518 return -1;
1519 ret:
1520 tcp->flags |= TCB_INSYSCALL;
1521 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001522 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001523 gettimeofday(&tcp->etime, NULL);
1524 return res;
1525}
1526
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001527/* Returns:
1528 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1529 * 1: ok, continue in trace_syscall().
1530 * other: error, trace_syscall() should print error indicator
1531 * ("????" etc) and bail out.
1532 */
1533static int
1534get_syscall_result(struct tcb *tcp)
1535{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001536#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001537 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1538 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001539#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001540# define SO_MASK 0x10000000
1541 {
1542 long flags;
1543 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1544 return -1;
1545 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &result) < 0)
1546 return -1;
1547 if (flags & SO_MASK)
1548 result = -result;
1549 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001550#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001551 /* Read complete register set in one go. */
1552 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1553 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001554#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001555 if (upeek(tcp, PT_R0, &r0) < 0)
1556 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001557#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001558 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001559 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001560#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001561 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001562 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001563#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001564# define IA64_PSR_IS ((long)1 << 34)
1565 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1566 ia32 = (psr & IA64_PSR_IS) != 0;
1567 if (upeek(tcp, PT_R8, &r8) < 0)
1568 return -1;
1569 if (upeek(tcp, PT_R10, &r10) < 0)
1570 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001571#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001572 /* Read complete register set in one go. */
1573 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1574 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001575#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001576 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1577 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001578#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001579 unsigned long long regs[38];
1580
1581 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1582 return -1;
1583 a3 = regs[REG_A3];
1584 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001585#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001586 if (upeek(tcp, REG_A3, &a3) < 0)
1587 return -1;
1588 if (upeek(tcp, REG_V0, &r2) < 0)
1589 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001590#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001591 if (upeek(tcp, REG_A3, &a3) < 0)
1592 return -1;
1593 if (upeek(tcp, REG_R0, &r0) < 0)
1594 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001595#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001596 /* Everything we need is in the current register set. */
1597 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1598 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001599#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001600 if (upeek(tcp, PT_GR28, &r28) < 0)
1601 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001602#elif defined(SH)
1603#elif defined(SH64)
1604#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001605 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1606 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001607#elif defined(TILE)
1608#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001609 if (upeek(tcp, 3 * 4, &r3) < 0)
1610 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001611#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001612
Denys Vlasenko523635f2012-02-25 02:44:25 +01001613#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001614 /* new syscall ABI returns result in R0 */
1615 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1616 return -1;
1617#elif defined(SH64)
1618 /* ABI defines result returned in r9 */
1619 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1620 return -1;
1621#endif
1622
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001623 return 1;
1624}
1625
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001626/* Called at each syscall exit.
1627 * Returns:
1628 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1629 * 1: ok, continue in trace_syscall().
1630 * other: error, trace_syscall() should print error indicator
1631 * ("????" etc) and bail out.
1632 */
1633static int
1634syscall_fixup_on_sysexit(struct tcb *tcp)
1635{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001636#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001637 if (syscall_mode != -ENOSYS)
1638 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001639 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001640 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1641 /*
1642 * Return from execve.
1643 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1644 * flag set for the post-execve SIGTRAP to see and reset.
1645 */
1646 gpr2 = 0;
1647 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001648#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001649 return 1;
1650}
1651
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001652/*
1653 * Check the syscall return value register value for whether it is
1654 * a negated errno code indicating an error, or a success return value.
1655 */
1656static inline int
1657is_negated_errno(unsigned long int val)
1658{
1659 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001660#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001661 if (personality_wordsize[current_personality] < sizeof(val)) {
1662 val = (unsigned int) val;
1663 max = (unsigned int) max;
1664 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001665#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001666 return val > max;
1667}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001668
1669static int
1670get_error(struct tcb *tcp)
1671{
1672 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001673 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001674 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001675 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1676 check_errno = 0;
1677 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001678#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001679 if (check_errno && is_negated_errno(gpr2)) {
1680 tcp->u_rval = -1;
1681 u_error = -gpr2;
1682 }
1683 else {
1684 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001685 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001686#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001687 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001688 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001689 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001690 }
1691 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001692 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001693 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001694#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001695 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001696 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001697 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001698 }
1699 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001700 tcp->u_rval = x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001701 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001702#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001703 if (ia32) {
1704 int err;
1705
1706 err = (int)r8;
1707 if (check_errno && is_negated_errno(err)) {
1708 tcp->u_rval = -1;
1709 u_error = -err;
1710 }
1711 else {
1712 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001713 }
1714 } else {
1715 if (check_errno && r10) {
1716 tcp->u_rval = -1;
1717 u_error = r8;
1718 } else {
1719 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001720 }
1721 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001722#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001723 if (check_errno && a3) {
1724 tcp->u_rval = -1;
1725 u_error = r2;
1726 } else {
1727 tcp->u_rval = r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001728 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001729#elif defined(POWERPC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001730 if (check_errno && is_negated_errno(result)) {
1731 tcp->u_rval = -1;
1732 u_error = -result;
1733 }
1734 else {
1735 tcp->u_rval = result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001736 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001737#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001738 if (check_errno && is_negated_errno(d0)) {
1739 tcp->u_rval = -1;
1740 u_error = -d0;
1741 }
1742 else {
1743 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001744 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001745#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001746 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1747 tcp->u_rval = -1;
1748 u_error = -regs.ARM_r0;
1749 }
1750 else {
1751 tcp->u_rval = regs.ARM_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001752 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001753#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001754 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1755 tcp->u_rval = -1;
1756 u_error = -regs.r12;
1757 }
1758 else {
1759 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001760 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001761#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001762 if (check_errno && is_negated_errno(r0)) {
1763 tcp->u_rval = -1;
1764 u_error = -r0;
1765 } else {
1766 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001767 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001768#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001769 if (check_errno && a3) {
1770 tcp->u_rval = -1;
1771 u_error = r0;
1772 }
1773 else {
1774 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001775 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001776#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001777 if (check_errno && regs.psr & PSR_C) {
1778 tcp->u_rval = -1;
1779 u_error = regs.u_regs[U_REG_O0];
1780 }
1781 else {
1782 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001783 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001784#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001785 if (check_errno && regs.tstate & 0x1100000000UL) {
1786 tcp->u_rval = -1;
1787 u_error = regs.u_regs[U_REG_O0];
1788 }
1789 else {
1790 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001791 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001792#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001793 if (check_errno && is_negated_errno(r28)) {
1794 tcp->u_rval = -1;
1795 u_error = -r28;
1796 }
1797 else {
1798 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001799 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001800#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001801 if (check_errno && is_negated_errno(r0)) {
1802 tcp->u_rval = -1;
1803 u_error = -r0;
1804 }
1805 else {
1806 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001807 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001808#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001809 if (check_errno && is_negated_errno(r9)) {
1810 tcp->u_rval = -1;
1811 u_error = -r9;
1812 }
1813 else {
1814 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001815 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001816#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001817 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1818 tcp->u_rval = -1;
1819 u_error = -r10;
1820 }
1821 else {
1822 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001823 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001824#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001825 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001826 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1827 return -1;
1828 if (check_errno && rval < 0 && rval > -nerrnos) {
1829 tcp->u_rval = -1;
1830 u_error = -rval;
1831 }
1832 else {
1833 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001834 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001835#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001836 if (check_errno && is_negated_errno(r3)) {
1837 tcp->u_rval = -1;
1838 u_error = -r3;
1839 }
1840 else {
1841 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001842 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001843#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001844 tcp->u_error = u_error;
1845 return 1;
1846}
1847
1848static void
1849dumpio(struct tcb *tcp)
1850{
1851 if (syserror(tcp))
1852 return;
1853 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1854 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001855 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001856 return;
1857 if (sysent[tcp->scno].sys_func == printargs)
1858 return;
1859 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1860 if (sysent[tcp->scno].sys_func == sys_read ||
1861 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001862 sysent[tcp->scno].sys_func == sys_recv ||
1863 sysent[tcp->scno].sys_func == sys_recvfrom)
1864 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1865 else if (sysent[tcp->scno].sys_func == sys_readv)
1866 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1867 return;
1868 }
1869 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1870 if (sysent[tcp->scno].sys_func == sys_write ||
1871 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001872 sysent[tcp->scno].sys_func == sys_send ||
1873 sysent[tcp->scno].sys_func == sys_sendto)
1874 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1875 else if (sysent[tcp->scno].sys_func == sys_writev)
1876 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1877 return;
1878 }
1879}
1880
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001881static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001882trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001883{
1884 int sys_res;
1885 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001886 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001887 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001888
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001889 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001890 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001891 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001892
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001893#if SUPPORTED_PERSONALITIES > 1
1894 update_personality(tcp, tcp->currpers);
1895#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001896 res = get_syscall_result(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001897 if (res == 0)
1898 return res;
1899 if (res == 1)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001900 res = syscall_fixup_on_sysexit(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001901 if (res == 0)
1902 return res;
1903 if (res == 1)
1904 res = get_error(tcp);
1905 if (res == 0)
1906 return res;
1907 if (res == 1)
1908 internal_syscall(tcp);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001909
Grant Edwards8a082772011-04-07 20:25:40 +00001910 if (res == 1 && filtered(tcp)) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001911 goto ret;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001912 }
1913
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001914 /* TODO: TCB_REPRINT is probably not necessary:
1915 * we can determine whether reprinting is needed
1916 * by examining printing_tcp. Something like:
1917 * if not in -ff mode, and printing_tcp != tcp,
1918 * then the log is not currenlty ends with *our*
1919 * syscall entry output, but with something else,
1920 * and we need to reprint.
1921 * If we'd implement this, printing_tcp = tcp
1922 * assignments in code below can be made more logical.
1923 */
1924
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001925 if (tcp->flags & TCB_REPRINT) {
1926 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001927 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001928 tprintf("<... syscall_%lu resumed> ", tcp->scno);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001929 else
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001930 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001931 }
1932
1933 if (cflag) {
1934 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02001935 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02001936 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001937 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001938 }
1939 }
1940
1941 if (res != 1) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001942 printing_tcp = tcp;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001943 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001944 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01001945 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001946 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001947 tcp->flags &= ~TCB_INSYSCALL;
1948 return res;
1949 }
1950
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001951 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001952 || (qual_flags[tcp->scno] & QUAL_RAW)) {
1953 printing_tcp = tcp;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001954 sys_res = printargs(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001955 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001956 /* FIXME: not_failing_only (IOW, option -z) is broken:
1957 * failure of syscall is known only after syscall return.
1958 * Thus we end up with something like this on, say, ENOENT:
1959 * open("doesnt_exist", O_RDONLY <unfinished ...>
1960 * {next syscall decode}
1961 * whereas the intended result is that open(...) line
1962 * is not shown at all.
1963 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001964 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02001965 goto ret; /* ignore failed syscalls */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001966 printing_tcp = tcp;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001967 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
1968 }
1969
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001970 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001971 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02001972 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001973 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001974 qual_flags[tcp->scno] & QUAL_RAW) {
1975 if (u_error)
1976 tprintf("= -1 (errno %ld)", u_error);
1977 else
1978 tprintf("= %#lx", tcp->u_rval);
1979 }
1980 else if (!(sys_res & RVAL_NONE) && u_error) {
1981 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01001982 /* Blocked signals do not interrupt any syscalls.
1983 * In this case syscalls don't return ERESTARTfoo codes.
1984 *
1985 * Deadly signals set to SIG_DFL interrupt syscalls
1986 * and kill the process regardless of which of the codes below
1987 * is returned by the interrupted syscall.
1988 * In some cases, kernel forces a kernel-generated deadly
1989 * signal to be unblocked and set to SIG_DFL (and thus cause
1990 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
1991 * or SIGILL. (The alternative is to leave process spinning
1992 * forever on the faulty instruction - not useful).
1993 *
1994 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
1995 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
1996 * but kernel will always restart them.
1997 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001998 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01001999 /* Most common type of signal-interrupted syscall exit code.
2000 * The system call will be restarted with the same arguments
2001 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2002 */
2003 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002004 break;
2005 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002006 /* Rare. For example, fork() returns this if interrupted.
2007 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2008 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002009 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002010 break;
2011 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002012 /* pause(), rt_sigsuspend() etc use this code.
2013 * SA_RESTART is ignored (assumed not set):
2014 * syscall won't restart (will return EINTR instead)
2015 * even after signal with SA_RESTART set.
2016 * However, after SIG_IGN or SIG_DFL signal it will.
2017 */
2018 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002019 break;
2020 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002021 /* Syscalls like nanosleep(), poll() which can't be
2022 * restarted with their original arguments use this
2023 * code. Kernel will execute restart_syscall() instead,
2024 * which changes arguments before restarting syscall.
2025 * SA_RESTART is ignored (assumed not set) similarly
2026 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2027 * since restart data is saved in "restart block"
2028 * in task struct, and if signal handler uses a syscall
2029 * which in turn saves another such restart block,
2030 * old data is lost and restart becomes impossible)
2031 */
2032 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002033 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002034 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002035 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002036 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002037 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002038 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002039 strerror(u_error));
2040 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002041 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002042 strerror(u_error));
2043 break;
2044 }
2045 if ((sys_res & RVAL_STR) && tcp->auxstr)
2046 tprintf(" (%s)", tcp->auxstr);
2047 }
2048 else {
2049 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002050 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002051 else {
2052 switch (sys_res & RVAL_MASK) {
2053 case RVAL_HEX:
2054 tprintf("= %#lx", tcp->u_rval);
2055 break;
2056 case RVAL_OCTAL:
2057 tprintf("= %#lo", tcp->u_rval);
2058 break;
2059 case RVAL_UDECIMAL:
2060 tprintf("= %lu", tcp->u_rval);
2061 break;
2062 case RVAL_DECIMAL:
2063 tprintf("= %ld", tcp->u_rval);
2064 break;
2065#ifdef HAVE_LONG_LONG
2066 case RVAL_LHEX:
2067 tprintf("= %#llx", tcp->u_lrval);
2068 break;
2069 case RVAL_LOCTAL:
2070 tprintf("= %#llo", tcp->u_lrval);
2071 break;
2072 case RVAL_LUDECIMAL:
2073 tprintf("= %llu", tcp->u_lrval);
2074 break;
2075 case RVAL_LDECIMAL:
2076 tprintf("= %lld", tcp->u_lrval);
2077 break;
2078#endif
2079 default:
2080 fprintf(stderr,
2081 "invalid rval format\n");
2082 break;
2083 }
2084 }
2085 if ((sys_res & RVAL_STR) && tcp->auxstr)
2086 tprintf(" (%s)", tcp->auxstr);
2087 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002088 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002089 tv_sub(&tv, &tv, &tcp->etime);
2090 tprintf(" <%ld.%06ld>",
2091 (long) tv.tv_sec, (long) tv.tv_usec);
2092 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002093 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002094 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002095 line_ended();
2096
Denys Vlasenko3b738812011-08-22 02:06:35 +02002097 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002098 tcp->flags &= ~TCB_INSYSCALL;
2099 return 0;
2100}
2101
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002102int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002103trace_syscall(struct tcb *tcp)
2104{
2105 return exiting(tcp) ?
2106 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2107}