blob: 546a8c41e6f51824eb3b2ed3d88139fe6e61c640 [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
Denys Vlasenko84703742012-02-25 02:38:52 +0100519#if !(defined(ALPHA) || defined(MIPS) || defined(__ARM_EABI__))
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}
583#endif
584
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200585int
586printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000587{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200588 if (entering(tcp)) {
589 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000590
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200591 for (i = 0; i < tcp->u_nargs; i++)
592 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
593 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000594 return 0;
595}
596
Denys Vlasenko72879c62012-02-27 14:18:02 +0100597int
598printargs_lu(struct tcb *tcp)
599{
600 if (entering(tcp)) {
601 int i;
602
603 for (i = 0; i < tcp->u_nargs; i++)
604 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
605 }
606 return 0;
607}
608
609int
610printargs_ld(struct tcb *tcp)
611{
612 if (entering(tcp)) {
613 int i;
614
615 for (i = 0; i < tcp->u_nargs; i++)
616 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
617 }
618 return 0;
619}
620
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200621long
622getrval2(struct tcb *tcp)
623{
624 long val = -1;
625
Denys Vlasenko523635f2012-02-25 02:44:25 +0100626#if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200627 struct pt_regs regs;
628 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
629 return -1;
630 val = regs.u_regs[U_REG_O1];
631#elif defined(SH)
632 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
633 return -1;
634#elif defined(IA64)
635 if (upeek(tcp, PT_R9, &val) < 0)
636 return -1;
637#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200638
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200639 return val;
640}
641
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200642int
643is_restart_error(struct tcb *tcp)
644{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200645 switch (tcp->u_error) {
646 case ERESTARTSYS:
647 case ERESTARTNOINTR:
648 case ERESTARTNOHAND:
649 case ERESTART_RESTARTBLOCK:
650 return 1;
651 default:
652 break;
653 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200654 return 0;
655}
656
Denys Vlasenko523635f2012-02-25 02:44:25 +0100657#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100658struct pt_regs i386_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100659#elif defined(X86_64)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100660/*
661 * On 32 bits, pt_regs and user_regs_struct are the same,
662 * but on 64 bits, user_regs_struct has six more fields:
663 * fs_base, gs_base, ds, es, fs, gs.
664 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
665 */
666static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100667#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200668long r8, r10, psr; /* TODO: make static? */
669long ia32 = 0; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100670#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +0200671static long result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100672#elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200673static long d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100674#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200675static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100676#elif defined(ARM)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200677static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100678#elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200679static long r0;
680static long a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100681#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200682static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100683#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200684static struct pt_regs regs;
685static unsigned long trap;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100686#elif defined(LINUX_MIPSN32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200687static long long a3;
688static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100689#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200690static long a3;
691static long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100692#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200693static long gpr2;
694static long pc;
695static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100696#elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200697static long r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100698#elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200699static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100700#elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200701static long r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100702#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200703static long r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100704#elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200705static long r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100706#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000707
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200708/* Returns:
709 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
710 * 1: ok, continue in trace_syscall().
711 * other: error, trace_syscall() should print error indicator
712 * ("????" etc) and bail out.
713 */
Denys Vlasenko9a36ae52011-08-24 16:47:32 +0200714static
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000715int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200716get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000717{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000718 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000719
Denys Vlasenko523635f2012-02-25 02:44:25 +0100720#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000721 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200722 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000723
724 if (syscall_mode != -ENOSYS) {
725 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000726 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000727 */
728 scno = syscall_mode;
729 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000730 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000731 * Old style of "passing" the scno via the SVC instruction.
732 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000733 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200734 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200735 static const int gpr_offset[16] = {
736 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
737 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
738 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
739 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
740 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000741
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000742 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000743 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000744 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000745 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000746 if (errno) {
747 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000748 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000749 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000750
751 /*
752 * We have to check if the SVC got executed directly or via an
753 * EXECUTE instruction. In case of EXECUTE it is necessary to do
754 * instruction decoding to derive the system call number.
755 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
756 * so that this doesn't work if a SVC opcode is part of an EXECUTE
757 * opcode. Since there is no way to find out the opcode size this
758 * is the best we can do...
759 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000760 if ((opcode & 0xff00) == 0x0a00) {
761 /* SVC opcode */
762 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000763 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000764 else {
765 /* SVC got executed by EXECUTE instruction */
766
767 /*
768 * Do instruction decoding of EXECUTE. If you really want to
769 * understand this, read the Principles of Operations.
770 */
771 svc_addr = (void *) (opcode & 0xfff);
772
773 tmp = 0;
774 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000775 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000776 return -1;
777 svc_addr += tmp;
778
779 tmp = 0;
780 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000781 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000782 return -1;
783 svc_addr += tmp;
784
Denys Vlasenkofb036672009-01-23 16:30:26 +0000785 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000786 if (errno)
787 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100788# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000789 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100790# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000791 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100792# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000793 tmp = 0;
794 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000795 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000796 return -1;
797
798 scno = (scno | tmp) & 0xff;
799 }
800 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100801#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000802 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000803 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100804# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200805 /* TODO: speed up strace by not doing this at every syscall.
806 * We only need to do it after execve.
807 */
808 int currpers;
809 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200810
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200811 /* Check for 64/32 bit mode. */
812 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
813 return -1;
814 /* SF is bit 0 of MSR */
815 if (val < 0)
816 currpers = 0;
817 else
818 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000819 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100820# endif
821#elif defined(AVR32)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200822 /* Read complete register set in one go. */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000823 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
824 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200825 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100826#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000827 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000828 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100829#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200830 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000831 return -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200832 scno = i386_regs.orig_eax;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100833#elif defined(X86_64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200834 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200835 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
836 return -1;
837 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +0000838
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200839 /* Check CS register value. On x86-64 linux it is:
840 * 0x33 for long mode (64 bit)
841 * 0x23 for compatibility mode (32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200842 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200843 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200844 case 0x23: currpers = 1; break;
845 case 0x33: currpers = 0; break;
846 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200847 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200848 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200849 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200850 currpers = current_personality;
851 break;
852 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100853# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200854 /* This version analyzes the opcode of a syscall instruction.
855 * (int 0x80 on i386 vs. syscall on x86-64)
856 * It works, but is too complicated.
857 */
858 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +0000859
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200860 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +0000861
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200862 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
863 rip -= 2;
864 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +0000865
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200866 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200867 if (errno)
868 fprintf(stderr, "ptrace_peektext failed: %s\n",
869 strerror(errno));
870 switch (call & 0xffff) {
871 /* x86-64: syscall = 0x0f 0x05 */
872 case 0x050f: currpers = 0; break;
873 /* i386: int 0x80 = 0xcd 0x80 */
874 case 0x80cd: currpers = 1; break;
875 default:
876 currpers = current_personality;
877 fprintf(stderr,
878 "Unknown syscall opcode (0x%04X) while "
879 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200880 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200881 break;
882 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100883# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000884 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100885#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000886# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200887 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000888 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200889 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200890 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200891 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000892 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200893 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000894 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200895 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100896#elif defined(ARM)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200897 /* Read complete register set in one go. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000898 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +0000899 return -1;
900
901 /*
902 * We only need to grab the syscall number on syscall entry.
903 */
904 if (regs.ARM_ip == 0) {
905 /*
906 * Note: we only deal with only 32-bit CPUs here.
907 */
908 if (regs.ARM_cpsr & 0x20) {
909 /*
910 * Get the Thumb-mode system call number
911 */
912 scno = regs.ARM_r7;
913 } else {
914 /*
915 * Get the ARM-mode system call number
916 */
917 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000918 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +0000919 if (errno)
920 return -1;
921
Roland McGrathf691bd22006-04-25 07:34:41 +0000922 /* Handle the EABI syscall convention. We do not
923 bother converting structures between the two
924 ABIs, but basic functionality should work even
925 if strace and the traced program have different
926 ABIs. */
927 if (scno == 0xef000000) {
928 scno = regs.ARM_r7;
929 } else {
930 if ((scno & 0x0ff00000) != 0x0f900000) {
931 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
932 scno);
933 return -1;
934 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000935
Roland McGrathf691bd22006-04-25 07:34:41 +0000936 /*
937 * Fixup the syscall number
938 */
939 scno &= 0x000fffff;
940 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000941 }
Roland McGrath56703312008-05-20 01:35:55 +0000942 if (scno & 0x0f0000) {
943 /*
944 * Handle ARM specific syscall
945 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000946 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +0000947 scno &= 0x0000ffff;
948 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000949 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +0000950
Roland McGrath0f87c492003-06-03 23:29:04 +0000951 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200952 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
953 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000954 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100955#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000956 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000957 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100958#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +0000959 unsigned long long regs[38];
960
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200961 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +0000962 return -1;
963 a3 = regs[REG_A3];
964 r2 = regs[REG_V0];
965
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200966 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200967 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200968 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100969 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200970 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000971 return 0;
972 }
Roland McGrath542c2c62008-05-20 01:11:56 +0000973 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100974#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000975 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000976 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200977 if (upeek(tcp, REG_V0, &scno) < 0)
978 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000979
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200980 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200981 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100982 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200983 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000984 return 0;
985 }
Wichert Akkermanf90da011999-10-31 21:15:38 +0000986 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100987#elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000988 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000989 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200990 if (upeek(tcp, REG_R0, &scno) < 0)
991 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000992
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200993 /*
994 * Do some sanity checks to figure out if it's
995 * really a syscall entry
996 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200997 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200998 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100999 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001000 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001001 return 0;
1002 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001003 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001004#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001005 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001006 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001007 return -1;
1008
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001009 /* Disassemble the syscall trap. */
1010 /* Retrieve the syscall trap instruction. */
1011 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001012# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001013 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1014 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001015# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001016 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001017# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001018 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001019 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001020
1021 /* Disassemble the trap to see what personality to use. */
1022 switch (trap) {
1023 case 0x91d02010:
1024 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001025 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001026 break;
1027 case 0x91d0206d:
1028 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001029 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001030 break;
1031 case 0x91d02000:
1032 /* SunOS syscall trap. (pers 1) */
1033 fprintf(stderr, "syscall: SunOS no support\n");
1034 return -1;
1035 case 0x91d02008:
1036 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001037 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001038 break;
1039 case 0x91d02009:
1040 /* NetBSD/FreeBSD syscall trap. */
1041 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1042 return -1;
1043 case 0x91d02027:
1044 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001045 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001046 break;
1047 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001048# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001049 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001050# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001051 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001052# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001053 return -1;
1054 }
1055
1056 /* Extract the system call number from the registers. */
1057 if (trap == 0x91d02027)
1058 scno = 156;
1059 else
1060 scno = regs.u_regs[U_REG_G1];
1061 if (scno == 0) {
1062 scno = regs.u_regs[U_REG_O0];
1063 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1064 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001065#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001066 if (upeek(tcp, PT_GR20, &scno) < 0)
1067 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001068#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001069 /*
1070 * In the new syscall ABI, the system call number is in R3.
1071 */
1072 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1073 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001074
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001075 if (scno < 0) {
1076 /* Odd as it may seem, a glibc bug has been known to cause
1077 glibc to issue bogus negative syscall numbers. So for
1078 our purposes, make strace print what it *should* have been */
1079 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001080 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001081 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001082 "Detected glibc bug: bogus system call"
1083 " number = %ld, correcting to %ld\n",
1084 scno,
1085 correct_scno);
1086 scno = correct_scno;
1087 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001088#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001089 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001090 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001091 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001092#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001093 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1094 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001095#elif defined(TILE)
Chris Metcalfc8c66982009-12-28 10:00:15 -05001096 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1097 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001098#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001099 if (upeek(tcp, 0, &scno) < 0)
1100 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001101#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001102
Denys Vlasenko523635f2012-02-25 02:44:25 +01001103#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001104 /* new syscall ABI returns result in R0 */
1105 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1106 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001107#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001108 /* ABI defines result returned in r9 */
1109 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1110 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001111#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001112
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001113 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001114 return 1;
1115}
1116
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001117/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001118 * Returns:
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001119 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
Roland McGratheb9e2e82009-06-02 16:49:22 -07001120 * 1: ok, continue in trace_syscall().
1121 * other: error, trace_syscall() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001122 * ("????" etc) and bail out.
1123 */
Roland McGratha4d48532005-06-08 20:45:28 +00001124static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001125syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001126{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001127 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001128#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001129 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001130 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001131 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1132 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001133 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001134#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001135 {
1136 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001137 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001138 rax = (int)rax; /* sign extend from 32 bits */
1139 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001140 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001141 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1142 return 0;
1143 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001144 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001145#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001146 /* TODO: we already fetched PT_GPR2 in get_scno
1147 * and stored it in syscall_mode, reuse it here
1148 * instead of re-fetching?
1149 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001150 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001151 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001152 if (syscall_mode != -ENOSYS)
1153 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001154 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001155 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001156 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001157 return 0;
1158 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001159#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001160 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001161 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001162 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001163 if (d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001164 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001165 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001166 return 0;
1167 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001168#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001169 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001170 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001171 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001172 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001173 if (ia32 && r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001174 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001175 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001176 return 0;
1177 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001178#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001179 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001180 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001181 if (r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001182 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001183 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001184 return 0;
1185 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001186#elif defined(MICROBLAZE)
1187 if (upeek(tcp, 3 * 4, &r3) < 0)
1188 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001189 if (r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001190 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001191 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001192 return 0;
1193 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001194#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001195 return 1;
1196}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001197
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001198static int
1199internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001200{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001201 /*
1202 * We must always trace a few critical system calls in order to
1203 * correctly support following forks in the presence of tracing
1204 * qualifiers.
1205 */
1206 int (*func)();
1207
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001208 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001209 return 0;
1210
1211 func = sysent[tcp->scno].sys_func;
1212
1213 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001214 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001215 || sys_clone == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001216 )
1217 return internal_fork(tcp);
1218
Denys Vlasenko84703742012-02-25 02:38:52 +01001219#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001220 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001221# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001222 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001223# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001224 )
1225 return internal_exec(tcp);
Roland McGrathc1e45922008-05-27 23:18:29 +00001226#endif
1227
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001228 return 0;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001229}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001230
Roland McGratha4d48532005-06-08 20:45:28 +00001231static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001232syscall_enter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001233{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001234 int i, nargs;
1235
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001236 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001237 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001238 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001239 nargs = tcp->u_nargs = MAX_ARGS;
1240
Denys Vlasenko523635f2012-02-25 02:44:25 +01001241#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001242 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001243 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1244 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001245#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001246 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001247 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1248 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001249#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001250 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001251 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001252 long rbs_end;
1253 /* be backwards compatible with kernel < 2.4.4... */
1254# ifndef PT_RBS_END
1255# define PT_RBS_END PT_AR_BSP
1256# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001257
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001258 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1259 return -1;
1260 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001261 return -1;
1262
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001263 sof = (cfm >> 0) & 0x7f;
1264 sol = (cfm >> 7) & 0x7f;
1265 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1266
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001267 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001268 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1269 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1270 return -1;
1271 }
1272 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001273 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1274 PT_R9 /* ECX = out1 */,
1275 PT_R10 /* EDX = out2 */,
1276 PT_R14 /* ESI = out3 */,
1277 PT_R15 /* EDI = out4 */,
1278 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001279
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001280 for (i = 0; i < nargs; ++i) {
1281 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1282 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001283 /* truncate away IVE sign-extension */
1284 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001285 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001286 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001287#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001288 /* N32 and N64 both use up to six registers. */
1289 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001290
1291 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1292 return -1;
1293
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001294 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001295 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001296# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001297 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001298# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001299 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001300#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001301 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001302 long sp;
1303
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001304 if (upeek(tcp, REG_SP, &sp) < 0)
1305 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001306 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001307 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1308 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001309 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001310 (char *)(tcp->u_arg + 4));
1311 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001312 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001313 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001314 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001315 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001316#elif defined(POWERPC)
1317# ifndef PT_ORIG_R3
1318# define PT_ORIG_R3 34
1319# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001320 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001321 if (upeek(tcp, (i==0) ?
1322 (sizeof(unsigned long) * PT_ORIG_R3) :
1323 ((i+PT_R3) * sizeof(unsigned long)),
1324 &tcp->u_arg[i]) < 0)
1325 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001326 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001327#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001328 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001329 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001330#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001331 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001332 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1333 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001334#elif defined(ARM)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001335 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001336 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001337#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001338 (void)i;
1339 (void)nargs;
1340 tcp->u_arg[0] = regs.r12;
1341 tcp->u_arg[1] = regs.r11;
1342 tcp->u_arg[2] = regs.r10;
1343 tcp->u_arg[3] = regs.r9;
1344 tcp->u_arg[4] = regs.r5;
1345 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001346#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001347 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 +02001348
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001349 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001350 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1351 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001352#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001353 static const int syscall_regs[MAX_ARGS] = {
1354 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1355 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001356 };
1357
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001358 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001359 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001360 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001361#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001362 int i;
1363 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001364 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001365
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001366 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001367 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1368 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001369#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001370 (void)i;
1371 (void)nargs;
1372 if (current_personality == 0) { /* x86-64 ABI */
1373 tcp->u_arg[0] = x86_64_regs.rdi;
1374 tcp->u_arg[1] = x86_64_regs.rsi;
1375 tcp->u_arg[2] = x86_64_regs.rdx;
1376 tcp->u_arg[3] = x86_64_regs.r10;
1377 tcp->u_arg[4] = x86_64_regs.r8;
1378 tcp->u_arg[5] = x86_64_regs.r9;
1379 } else { /* i386 ABI */
1380 /* Sign-extend lower 32 bits */
1381 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1382 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1383 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1384 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1385 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1386 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1387 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001388#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001389 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001390 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1391 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001392#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001393 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001394 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001395 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001396 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001397
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001398 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001399 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1400 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001401#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001402 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001403 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1404 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001405#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001406 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001407 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1408 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001409#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001410 (void)i;
1411 (void)nargs;
1412 tcp->u_arg[0] = i386_regs.ebx;
1413 tcp->u_arg[1] = i386_regs.ecx;
1414 tcp->u_arg[2] = i386_regs.edx;
1415 tcp->u_arg[3] = i386_regs.esi;
1416 tcp->u_arg[4] = i386_regs.edi;
1417 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001418#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001419 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001420 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1421 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001422#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001423 return 1;
1424}
1425
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001426static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001427trace_syscall_entering(struct tcb *tcp)
1428{
1429 int res, scno_good;
1430
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001431#if defined TCB_WAITEXECVE
1432 if (tcp->flags & TCB_WAITEXECVE) {
1433 /* This is the post-execve SIGTRAP. */
1434 tcp->flags &= ~TCB_WAITEXECVE;
1435 return 0;
1436 }
1437#endif
1438
Denys Vlasenko06602d92011-08-24 17:53:52 +02001439 scno_good = res = get_scno(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001440 if (res == 0)
1441 return res;
1442 if (res == 1)
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001443 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001444 if (res == 0)
1445 return res;
1446 if (res == 1)
1447 res = syscall_enter(tcp);
1448 if (res == 0)
1449 return res;
1450
1451 if (res != 1) {
1452 printleader(tcp);
1453 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001454 if (scno_good != 1)
1455 tprintf("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001456 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001457 tprintf("syscall_%lu(", tcp->scno);
1458 else
1459 tprintf("%s(", sysent[tcp->scno].sys_name);
1460 /*
1461 * " <unavailable>" will be added later by the code which
1462 * detects ptrace errors.
1463 */
1464 goto ret;
1465 }
1466
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001467#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1468 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001469# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001470 if (sysent[tcp->scno].sys_func == sys_socketcall) {
1471 decode_subcall(tcp, SYS_socket_subcall,
1472 SYS_socket_nsubcalls, deref_style);
1473 break;
1474 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001475# endif
1476# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001477 if (sysent[tcp->scno].sys_func == sys_ipc) {
1478 decode_subcall(tcp, SYS_ipc_subcall,
1479 SYS_ipc_nsubcalls, shift_style);
1480 break;
1481 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001482# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001483 break;
1484 }
1485#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1486
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001487 internal_syscall(tcp);
1488
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001489 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001490 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1491 (tracing_paths && !pathtrace_match(tcp))) {
1492 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1493 return 0;
1494 }
1495
1496 tcp->flags &= ~TCB_FILTERED;
1497
1498 if (cflag == CFLAG_ONLY_STATS) {
1499 res = 0;
1500 goto ret;
1501 }
1502
1503 printleader(tcp);
1504 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001505 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001506 tprintf("syscall_%lu(", tcp->scno);
1507 else
1508 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001509 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001510 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1511 sysent[tcp->scno].sys_func != sys_exit))
1512 res = printargs(tcp);
1513 else
1514 res = (*sysent[tcp->scno].sys_func)(tcp);
1515
1516 if (fflush(tcp->outf) == EOF)
1517 return -1;
1518 ret:
1519 tcp->flags |= TCB_INSYSCALL;
1520 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001521 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001522 gettimeofday(&tcp->etime, NULL);
1523 return res;
1524}
1525
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001526/* Returns:
1527 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1528 * 1: ok, continue in trace_syscall().
1529 * other: error, trace_syscall() should print error indicator
1530 * ("????" etc) and bail out.
1531 */
1532static int
1533get_syscall_result(struct tcb *tcp)
1534{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001535#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001536 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1537 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001538#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001539# define SO_MASK 0x10000000
1540 {
1541 long flags;
1542 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1543 return -1;
1544 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &result) < 0)
1545 return -1;
1546 if (flags & SO_MASK)
1547 result = -result;
1548 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001549#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001550 /* Read complete register set in one go. */
1551 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1552 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001553#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001554 if (upeek(tcp, PT_R0, &r0) < 0)
1555 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001556#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001557 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001558 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001559#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001560 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001561 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001562#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001563# define IA64_PSR_IS ((long)1 << 34)
1564 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1565 ia32 = (psr & IA64_PSR_IS) != 0;
1566 if (upeek(tcp, PT_R8, &r8) < 0)
1567 return -1;
1568 if (upeek(tcp, PT_R10, &r10) < 0)
1569 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001570#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001571 /* Read complete register set in one go. */
1572 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1573 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001574#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001575 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1576 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001577#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001578 unsigned long long regs[38];
1579
1580 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1581 return -1;
1582 a3 = regs[REG_A3];
1583 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001584#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001585 if (upeek(tcp, REG_A3, &a3) < 0)
1586 return -1;
1587 if (upeek(tcp, REG_V0, &r2) < 0)
1588 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001589#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001590 if (upeek(tcp, REG_A3, &a3) < 0)
1591 return -1;
1592 if (upeek(tcp, REG_R0, &r0) < 0)
1593 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001594#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001595 /* Everything we need is in the current register set. */
1596 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1597 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001598#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001599 if (upeek(tcp, PT_GR28, &r28) < 0)
1600 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001601#elif defined(SH)
1602#elif defined(SH64)
1603#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001604 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1605 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001606#elif defined(TILE)
1607#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001608 if (upeek(tcp, 3 * 4, &r3) < 0)
1609 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001610#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001611
Denys Vlasenko523635f2012-02-25 02:44:25 +01001612#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001613 /* new syscall ABI returns result in R0 */
1614 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1615 return -1;
1616#elif defined(SH64)
1617 /* ABI defines result returned in r9 */
1618 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1619 return -1;
1620#endif
1621
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001622 return 1;
1623}
1624
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001625/* Called at each syscall exit.
1626 * Returns:
1627 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1628 * 1: ok, continue in trace_syscall().
1629 * other: error, trace_syscall() should print error indicator
1630 * ("????" etc) and bail out.
1631 */
1632static int
1633syscall_fixup_on_sysexit(struct tcb *tcp)
1634{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001635#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001636 if (syscall_mode != -ENOSYS)
1637 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001638 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001639 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1640 /*
1641 * Return from execve.
1642 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1643 * flag set for the post-execve SIGTRAP to see and reset.
1644 */
1645 gpr2 = 0;
1646 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001647#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001648 return 1;
1649}
1650
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001651/*
1652 * Check the syscall return value register value for whether it is
1653 * a negated errno code indicating an error, or a success return value.
1654 */
1655static inline int
1656is_negated_errno(unsigned long int val)
1657{
1658 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001659#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001660 if (personality_wordsize[current_personality] < sizeof(val)) {
1661 val = (unsigned int) val;
1662 max = (unsigned int) max;
1663 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001664#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001665 return val > max;
1666}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001667
1668static int
1669get_error(struct tcb *tcp)
1670{
1671 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001672 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001673 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001674 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1675 check_errno = 0;
1676 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001677#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001678 if (check_errno && is_negated_errno(gpr2)) {
1679 tcp->u_rval = -1;
1680 u_error = -gpr2;
1681 }
1682 else {
1683 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001684 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001685#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001686 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001687 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001688 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001689 }
1690 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001691 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001692 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001693#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001694 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001695 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001696 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001697 }
1698 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001699 tcp->u_rval = x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001700 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001701#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001702 if (ia32) {
1703 int err;
1704
1705 err = (int)r8;
1706 if (check_errno && is_negated_errno(err)) {
1707 tcp->u_rval = -1;
1708 u_error = -err;
1709 }
1710 else {
1711 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001712 }
1713 } else {
1714 if (check_errno && r10) {
1715 tcp->u_rval = -1;
1716 u_error = r8;
1717 } else {
1718 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001719 }
1720 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001721#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001722 if (check_errno && a3) {
1723 tcp->u_rval = -1;
1724 u_error = r2;
1725 } else {
1726 tcp->u_rval = r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001727 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001728#elif defined(POWERPC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001729 if (check_errno && is_negated_errno(result)) {
1730 tcp->u_rval = -1;
1731 u_error = -result;
1732 }
1733 else {
1734 tcp->u_rval = result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001735 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001736#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001737 if (check_errno && is_negated_errno(d0)) {
1738 tcp->u_rval = -1;
1739 u_error = -d0;
1740 }
1741 else {
1742 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001743 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001744#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001745 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1746 tcp->u_rval = -1;
1747 u_error = -regs.ARM_r0;
1748 }
1749 else {
1750 tcp->u_rval = regs.ARM_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001751 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001752#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001753 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1754 tcp->u_rval = -1;
1755 u_error = -regs.r12;
1756 }
1757 else {
1758 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001759 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001760#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001761 if (check_errno && is_negated_errno(r0)) {
1762 tcp->u_rval = -1;
1763 u_error = -r0;
1764 } else {
1765 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001766 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001767#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001768 if (check_errno && a3) {
1769 tcp->u_rval = -1;
1770 u_error = r0;
1771 }
1772 else {
1773 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001774 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001775#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001776 if (check_errno && regs.psr & PSR_C) {
1777 tcp->u_rval = -1;
1778 u_error = regs.u_regs[U_REG_O0];
1779 }
1780 else {
1781 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001782 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001783#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001784 if (check_errno && regs.tstate & 0x1100000000UL) {
1785 tcp->u_rval = -1;
1786 u_error = regs.u_regs[U_REG_O0];
1787 }
1788 else {
1789 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001790 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001791#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001792 if (check_errno && is_negated_errno(r28)) {
1793 tcp->u_rval = -1;
1794 u_error = -r28;
1795 }
1796 else {
1797 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001798 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001799#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001800 if (check_errno && is_negated_errno(r0)) {
1801 tcp->u_rval = -1;
1802 u_error = -r0;
1803 }
1804 else {
1805 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001806 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001807#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001808 if (check_errno && is_negated_errno(r9)) {
1809 tcp->u_rval = -1;
1810 u_error = -r9;
1811 }
1812 else {
1813 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001814 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001815#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001816 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1817 tcp->u_rval = -1;
1818 u_error = -r10;
1819 }
1820 else {
1821 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001822 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001823#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001824 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001825 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1826 return -1;
1827 if (check_errno && rval < 0 && rval > -nerrnos) {
1828 tcp->u_rval = -1;
1829 u_error = -rval;
1830 }
1831 else {
1832 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001833 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001834#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001835 if (check_errno && is_negated_errno(r3)) {
1836 tcp->u_rval = -1;
1837 u_error = -r3;
1838 }
1839 else {
1840 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001841 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001842#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001843 tcp->u_error = u_error;
1844 return 1;
1845}
1846
1847static void
1848dumpio(struct tcb *tcp)
1849{
1850 if (syserror(tcp))
1851 return;
1852 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1853 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001854 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001855 return;
1856 if (sysent[tcp->scno].sys_func == printargs)
1857 return;
1858 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1859 if (sysent[tcp->scno].sys_func == sys_read ||
1860 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001861 sysent[tcp->scno].sys_func == sys_recv ||
1862 sysent[tcp->scno].sys_func == sys_recvfrom)
1863 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1864 else if (sysent[tcp->scno].sys_func == sys_readv)
1865 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1866 return;
1867 }
1868 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1869 if (sysent[tcp->scno].sys_func == sys_write ||
1870 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001871 sysent[tcp->scno].sys_func == sys_send ||
1872 sysent[tcp->scno].sys_func == sys_sendto)
1873 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1874 else if (sysent[tcp->scno].sys_func == sys_writev)
1875 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1876 return;
1877 }
1878}
1879
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001880static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001881trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001882{
1883 int sys_res;
1884 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001885 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001886 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001887
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001888 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001889 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001890 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001891
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001892#if SUPPORTED_PERSONALITIES > 1
1893 update_personality(tcp, tcp->currpers);
1894#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001895 res = get_syscall_result(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001896 if (res == 0)
1897 return res;
1898 if (res == 1)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001899 res = syscall_fixup_on_sysexit(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001900 if (res == 0)
1901 return res;
1902 if (res == 1)
1903 res = get_error(tcp);
1904 if (res == 0)
1905 return res;
1906 if (res == 1)
1907 internal_syscall(tcp);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001908
Grant Edwards8a082772011-04-07 20:25:40 +00001909 if (res == 1 && filtered(tcp)) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001910 goto ret;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001911 }
1912
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001913 /* TODO: TCB_REPRINT is probably not necessary:
1914 * we can determine whether reprinting is needed
1915 * by examining printing_tcp. Something like:
1916 * if not in -ff mode, and printing_tcp != tcp,
1917 * then the log is not currenlty ends with *our*
1918 * syscall entry output, but with something else,
1919 * and we need to reprint.
1920 * If we'd implement this, printing_tcp = tcp
1921 * assignments in code below can be made more logical.
1922 */
1923
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001924 if (tcp->flags & TCB_REPRINT) {
1925 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001926 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001927 tprintf("<... syscall_%lu resumed> ", tcp->scno);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001928 else
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001929 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001930 }
1931
1932 if (cflag) {
1933 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02001934 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02001935 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001936 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001937 }
1938 }
1939
1940 if (res != 1) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001941 printing_tcp = tcp;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001942 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001943 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01001944 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001945 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001946 tcp->flags &= ~TCB_INSYSCALL;
1947 return res;
1948 }
1949
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001950 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001951 || (qual_flags[tcp->scno] & QUAL_RAW)) {
1952 printing_tcp = tcp;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001953 sys_res = printargs(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001954 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001955 /* FIXME: not_failing_only (IOW, option -z) is broken:
1956 * failure of syscall is known only after syscall return.
1957 * Thus we end up with something like this on, say, ENOENT:
1958 * open("doesnt_exist", O_RDONLY <unfinished ...>
1959 * {next syscall decode}
1960 * whereas the intended result is that open(...) line
1961 * is not shown at all.
1962 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001963 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02001964 goto ret; /* ignore failed syscalls */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001965 printing_tcp = tcp;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001966 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
1967 }
1968
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001969 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001970 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02001971 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001972 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001973 qual_flags[tcp->scno] & QUAL_RAW) {
1974 if (u_error)
1975 tprintf("= -1 (errno %ld)", u_error);
1976 else
1977 tprintf("= %#lx", tcp->u_rval);
1978 }
1979 else if (!(sys_res & RVAL_NONE) && u_error) {
1980 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01001981 /* Blocked signals do not interrupt any syscalls.
1982 * In this case syscalls don't return ERESTARTfoo codes.
1983 *
1984 * Deadly signals set to SIG_DFL interrupt syscalls
1985 * and kill the process regardless of which of the codes below
1986 * is returned by the interrupted syscall.
1987 * In some cases, kernel forces a kernel-generated deadly
1988 * signal to be unblocked and set to SIG_DFL (and thus cause
1989 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
1990 * or SIGILL. (The alternative is to leave process spinning
1991 * forever on the faulty instruction - not useful).
1992 *
1993 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
1994 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
1995 * but kernel will always restart them.
1996 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001997 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01001998 /* Most common type of signal-interrupted syscall exit code.
1999 * The system call will be restarted with the same arguments
2000 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2001 */
2002 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002003 break;
2004 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002005 /* Rare. For example, fork() returns this if interrupted.
2006 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2007 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002008 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002009 break;
2010 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002011 /* pause(), rt_sigsuspend() etc use this code.
2012 * SA_RESTART is ignored (assumed not set):
2013 * syscall won't restart (will return EINTR instead)
2014 * even after signal with SA_RESTART set.
2015 * However, after SIG_IGN or SIG_DFL signal it will.
2016 */
2017 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002018 break;
2019 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002020 /* Syscalls like nanosleep(), poll() which can't be
2021 * restarted with their original arguments use this
2022 * code. Kernel will execute restart_syscall() instead,
2023 * which changes arguments before restarting syscall.
2024 * SA_RESTART is ignored (assumed not set) similarly
2025 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2026 * since restart data is saved in "restart block"
2027 * in task struct, and if signal handler uses a syscall
2028 * which in turn saves another such restart block,
2029 * old data is lost and restart becomes impossible)
2030 */
2031 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002032 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002033 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002034 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002035 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002036 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002037 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002038 strerror(u_error));
2039 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002040 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002041 strerror(u_error));
2042 break;
2043 }
2044 if ((sys_res & RVAL_STR) && tcp->auxstr)
2045 tprintf(" (%s)", tcp->auxstr);
2046 }
2047 else {
2048 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002049 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002050 else {
2051 switch (sys_res & RVAL_MASK) {
2052 case RVAL_HEX:
2053 tprintf("= %#lx", tcp->u_rval);
2054 break;
2055 case RVAL_OCTAL:
2056 tprintf("= %#lo", tcp->u_rval);
2057 break;
2058 case RVAL_UDECIMAL:
2059 tprintf("= %lu", tcp->u_rval);
2060 break;
2061 case RVAL_DECIMAL:
2062 tprintf("= %ld", tcp->u_rval);
2063 break;
2064#ifdef HAVE_LONG_LONG
2065 case RVAL_LHEX:
2066 tprintf("= %#llx", tcp->u_lrval);
2067 break;
2068 case RVAL_LOCTAL:
2069 tprintf("= %#llo", tcp->u_lrval);
2070 break;
2071 case RVAL_LUDECIMAL:
2072 tprintf("= %llu", tcp->u_lrval);
2073 break;
2074 case RVAL_LDECIMAL:
2075 tprintf("= %lld", tcp->u_lrval);
2076 break;
2077#endif
2078 default:
2079 fprintf(stderr,
2080 "invalid rval format\n");
2081 break;
2082 }
2083 }
2084 if ((sys_res & RVAL_STR) && tcp->auxstr)
2085 tprintf(" (%s)", tcp->auxstr);
2086 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002087 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002088 tv_sub(&tv, &tv, &tcp->etime);
2089 tprintf(" <%ld.%06ld>",
2090 (long) tv.tv_sec, (long) tv.tv_usec);
2091 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002092 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002093 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002094 line_ended();
2095
Denys Vlasenko3b738812011-08-22 02:06:35 +02002096 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002097 tcp->flags &= ~TCB_INSYSCALL;
2098 return 0;
2099}
2100
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002101int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002102trace_syscall(struct tcb *tcp)
2103{
2104 return exiting(tcp) ?
2105 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2106}