blob: 3f157b2a957bf352385227e852d98dba941f4450 [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.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000032 */
33
34#include "defs.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000035#include <sys/user.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000036#include <sys/param.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000037
Wichert Akkerman15dea971999-10-06 13:06:34 +000038#ifdef HAVE_SYS_REG_H
Denys Vlasenko523635f2012-02-25 02:44:25 +010039# include <sys/reg.h>
40# ifndef PTRACE_PEEKUSR
41# define PTRACE_PEEKUSR PTRACE_PEEKUSER
42# endif
Wichert Akkermanfaf72222000-02-19 23:59:03 +000043#elif defined(HAVE_LINUX_PTRACE_H)
Denys Vlasenko523635f2012-02-25 02:44:25 +010044# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000045# ifdef HAVE_STRUCT_IA64_FPREG
46# define ia64_fpreg XXX_ia64_fpreg
47# endif
48# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
49# define pt_all_user_regs XXX_pt_all_user_regs
50# endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010051# include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000052# undef ia64_fpreg
53# undef pt_all_user_regs
Wichert Akkerman15dea971999-10-06 13:06:34 +000054#endif
55
Denys Vlasenko84703742012-02-25 02:38:52 +010056#if defined(SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +000057# undef PTRACE_GETREGS
58# define PTRACE_GETREGS PTRACE_GETREGS64
59# undef PTRACE_SETREGS
60# define PTRACE_SETREGS PTRACE_SETREGS64
Denys Vlasenko84703742012-02-25 02:38:52 +010061#endif
Roland McGrath6d1a65c2004-07-12 07:44:08 +000062
Denys Vlasenko84703742012-02-25 02:38:52 +010063#if defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000064# include <asm/ptrace_offsets.h>
65# include <asm/rse.h>
66#endif
67
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000068#ifndef ERESTARTSYS
Denys Vlasenko523635f2012-02-25 02:44:25 +010069# define ERESTARTSYS 512
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000070#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010071#ifndef ERESTARTNOINTR
Denys Vlasenko523635f2012-02-25 02:44:25 +010072# define ERESTARTNOINTR 513
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000073#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010074#ifndef ERESTARTNOHAND
75# define ERESTARTNOHAND 514 /* restart if no handler */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000076#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010077#ifndef ERESTART_RESTARTBLOCK
Denys Vlasenko523635f2012-02-25 02:44:25 +010078# define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
Roland McGrath9c555e72003-07-09 09:47:59 +000079#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010080
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000081#ifndef NSIG
Denys Vlasenko523635f2012-02-25 02:44:25 +010082# warning: NSIG is not defined, using 32
83# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000084#endif
85#ifdef ARM
Denys Vlasenko041b3ee2011-08-18 12:48:56 +020086/* Ugh. Is this really correct? ARM has no RT signals?! */
Denys Vlasenko523635f2012-02-25 02:44:25 +010087# undef NSIG
88# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000089#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000090
91#include "syscall.h"
92
93/* Define these shorthand notations to simplify the syscallent files. */
Roland McGrath2fe7b132005-07-05 03:25:35 +000094#define TD TRACE_DESC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000095#define TF TRACE_FILE
96#define TI TRACE_IPC
97#define TN TRACE_NETWORK
98#define TP TRACE_PROCESS
99#define TS TRACE_SIGNAL
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000100#define NF SYSCALL_NEVER_FAILS
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200101#define MA MAX_ARGS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102
Roland McGrathee36ce12004-09-04 03:53:10 +0000103static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000104#include "syscallent.h"
105};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000106
107#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000108static const struct sysent sysent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100109# include "syscallent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000110};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200111#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000112
113#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000114static const struct sysent sysent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100115# include "syscallent2.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/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000120#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121#undef TF
122#undef TI
123#undef TN
124#undef TP
125#undef TS
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000126#undef NF
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200127#undef MA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000128
Denys Vlasenko39fca622011-08-20 02:12:33 +0200129/*
130 * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
131 * program `ioctlsort', such that the list is sorted by the `code' field.
132 * This has the side-effect of resolving the _IO.. macros into
133 * plain integers, eliminating the need to include here everything
134 * in "/usr/include".
135 */
136
Roland McGrathee36ce12004-09-04 03:53:10 +0000137static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000138#include "errnoent.h"
139};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200140static const char *const signalent0[] = {
141#include "signalent.h"
142};
143static const struct ioctlent ioctlent0[] = {
144#include "ioctlent.h"
145};
146enum { nsyscalls0 = ARRAY_SIZE(sysent0) };
147enum { nerrnos0 = ARRAY_SIZE(errnoent0) };
148enum { nsignals0 = ARRAY_SIZE(signalent0) };
149enum { nioctlents0 = ARRAY_SIZE(ioctlent0) };
150int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000151
152#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000153static const char *const errnoent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100154# include "errnoent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000155};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200156static const char *const signalent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100157# include "signalent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200158};
159static const struct ioctlent ioctlent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100160# include "ioctlent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200161};
162enum { nsyscalls1 = ARRAY_SIZE(sysent1) };
163enum { nerrnos1 = ARRAY_SIZE(errnoent1) };
164enum { nsignals1 = ARRAY_SIZE(signalent1) };
165enum { nioctlents1 = ARRAY_SIZE(ioctlent1) };
166int qual_flags1[MAX_QUALS];
167#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000168
169#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000170static const char *const errnoent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100171# include "errnoent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000172};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200173static const char *const signalent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100174# include "signalent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200175};
176static const struct ioctlent ioctlent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100177# include "ioctlent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200178};
179enum { nsyscalls2 = ARRAY_SIZE(sysent2) };
180enum { nerrnos2 = ARRAY_SIZE(errnoent2) };
181enum { nsignals2 = ARRAY_SIZE(signalent2) };
182enum { nioctlents2 = ARRAY_SIZE(ioctlent2) };
183int qual_flags2[MAX_QUALS];
184#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000185
Denys Vlasenko39fca622011-08-20 02:12:33 +0200186const struct sysent *sysent;
Roland McGrathee36ce12004-09-04 03:53:10 +0000187const char *const *errnoent;
Denys Vlasenko39fca622011-08-20 02:12:33 +0200188const char *const *signalent;
189const struct ioctlent *ioctlent;
Denys Vlasenkoafc64032011-08-23 13:29:01 +0200190unsigned nsyscalls;
191unsigned nerrnos;
192unsigned nsignals;
193unsigned nioctlents;
Denys Vlasenko39fca622011-08-20 02:12:33 +0200194int *qual_flags;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000195
196int current_personality;
197
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000198#ifndef PERSONALITY0_WORDSIZE
199# define PERSONALITY0_WORDSIZE sizeof(long)
200#endif
201const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
202 PERSONALITY0_WORDSIZE,
203#if SUPPORTED_PERSONALITIES > 1
204 PERSONALITY1_WORDSIZE,
205#endif
206#if SUPPORTED_PERSONALITIES > 2
207 PERSONALITY2_WORDSIZE,
208#endif
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200209};
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000210
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200211void
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000212set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000213{
214 switch (personality) {
215 case 0:
216 errnoent = errnoent0;
217 nerrnos = nerrnos0;
218 sysent = sysent0;
219 nsyscalls = nsyscalls0;
220 ioctlent = ioctlent0;
221 nioctlents = nioctlents0;
222 signalent = signalent0;
223 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000224 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000225 break;
226
227#if SUPPORTED_PERSONALITIES >= 2
228 case 1:
229 errnoent = errnoent1;
230 nerrnos = nerrnos1;
231 sysent = sysent1;
232 nsyscalls = nsyscalls1;
233 ioctlent = ioctlent1;
234 nioctlents = nioctlents1;
235 signalent = signalent1;
236 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000237 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000238 break;
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200239#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000240
241#if SUPPORTED_PERSONALITIES >= 3
242 case 2:
243 errnoent = errnoent2;
244 nerrnos = nerrnos2;
245 sysent = sysent2;
246 nsyscalls = nsyscalls2;
247 ioctlent = ioctlent2;
248 nioctlents = nioctlents2;
249 signalent = signalent2;
250 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000251 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000252 break;
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200253#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000254 }
255
256 current_personality = personality;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000257}
258
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000259#if SUPPORTED_PERSONALITIES > 1
260static void
261update_personality(struct tcb *tcp, int personality)
262{
263 if (personality == current_personality)
264 return;
265 set_personality(personality);
266
267 if (personality == tcp->currpers)
268 return;
269 tcp->currpers = personality;
270
Denys Vlasenko523635f2012-02-25 02:44:25 +0100271# if defined(POWERPC64) || defined(X86_64)
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000272 if (!qflag) {
273 static const char *const names[] = {"64 bit", "32 bit"};
274 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
275 tcp->pid, names[personality]);
276 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100277# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000278}
279#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000280
Roland McGrath9797ceb2002-12-30 10:23:00 +0000281static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000282
Roland McGrathe10e62a2004-09-04 04:20:43 +0000283static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000284 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000285 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000286 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000287 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000288} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000289 { QUAL_TRACE, "trace", qual_syscall, "system call" },
290 { QUAL_TRACE, "t", qual_syscall, "system call" },
291 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
292 { QUAL_ABBREV, "a", qual_syscall, "system call" },
293 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
294 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
295 { QUAL_RAW, "raw", qual_syscall, "system call" },
296 { QUAL_RAW, "x", qual_syscall, "system call" },
297 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
298 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
299 { QUAL_SIGNAL, "s", qual_signal, "signal" },
300 { QUAL_FAULT, "fault", qual_fault, "fault" },
301 { QUAL_FAULT, "faults", qual_fault, "fault" },
302 { QUAL_FAULT, "m", qual_fault, "fault" },
303 { QUAL_READ, "read", qual_desc, "descriptor" },
304 { QUAL_READ, "reads", qual_desc, "descriptor" },
305 { QUAL_READ, "r", qual_desc, "descriptor" },
306 { QUAL_WRITE, "write", qual_desc, "descriptor" },
307 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
308 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000309 { 0, NULL, NULL, NULL },
310};
311
Roland McGrath9797ceb2002-12-30 10:23:00 +0000312static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000313qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000314{
Roland McGrath138c6a32006-01-12 09:50:49 +0000315 if (pers == 0 || pers < 0) {
316 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000317 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000318 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000319 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000320 }
321
322#if SUPPORTED_PERSONALITIES >= 2
323 if (pers == 1 || pers < 0) {
324 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000325 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000326 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000327 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000328 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100329#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000330
331#if SUPPORTED_PERSONALITIES >= 3
332 if (pers == 2 || pers < 0) {
333 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000334 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000335 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000336 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000337 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100338#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000339}
340
341static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000342qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000343{
344 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000345 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000346
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000347 if (isdigit((unsigned char)*s)) {
348 int i = atoi(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000349 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000350 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000351 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000352 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000353 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000354 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000355 if (strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000356 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000357 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000358 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000359
360#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000361 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000362 if (strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000363 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000364 rc = 0;
365 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100366#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000367
368#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000369 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000370 if (strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000371 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000372 rc = 0;
373 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100374#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000375
Roland McGrathfe6b3522005-02-02 04:40:11 +0000376 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000377}
378
379static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000380qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000381{
382 int i;
383 char buf[32];
384
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000385 if (isdigit((unsigned char)*s)) {
386 int signo = atoi(s);
387 if (signo < 0 || signo >= MAX_QUALS)
388 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000389 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000390 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000391 }
Roland McGrathd62b6712004-03-02 06:52:01 +0000392 if (strlen(s) >= sizeof buf)
Roland McGrathfe6b3522005-02-02 04:40:11 +0000393 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000394 strcpy(buf, s);
395 s = buf;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000396 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000397 s += 3;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000398 for (i = 0; i <= NSIG; i++)
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000399 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000400 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000401 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000402 }
Roland McGrath76421df2005-02-02 03:51:18 +0000403 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000404}
405
406static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000407qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000408{
409 return -1;
410}
411
412static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000413qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000414{
Roland McGrath48a035f2006-01-12 09:45:56 +0000415 if (isdigit((unsigned char)*s)) {
Roland McGrathfe6b3522005-02-02 04:40:11 +0000416 int desc = atoi(s);
417 if (desc < 0 || desc >= MAX_QUALS)
418 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000419 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000420 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000421 }
422 return -1;
423}
424
425static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000426lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000427{
428 if (strcmp(s, "file") == 0)
429 return TRACE_FILE;
430 if (strcmp(s, "ipc") == 0)
431 return TRACE_IPC;
432 if (strcmp(s, "network") == 0)
433 return TRACE_NETWORK;
434 if (strcmp(s, "process") == 0)
435 return TRACE_PROCESS;
436 if (strcmp(s, "signal") == 0)
437 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000438 if (strcmp(s, "desc") == 0)
439 return TRACE_DESC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000440 return -1;
441}
442
443void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000444qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000445{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000446 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000447 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000448 char *copy;
449 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000450 int i, n;
451
452 opt = &qual_options[0];
453 for (i = 0; (p = qual_options[i].option_name); i++) {
454 n = strlen(p);
455 if (strncmp(s, p, n) == 0 && s[n] == '=') {
456 opt = &qual_options[i];
457 s += n + 1;
458 break;
459 }
460 }
461 not = 0;
462 if (*s == '!') {
463 not = 1;
464 s++;
465 }
466 if (strcmp(s, "none") == 0) {
467 not = 1 - not;
468 s = "all";
469 }
470 if (strcmp(s, "all") == 0) {
471 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000472 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000473 }
474 return;
475 }
476 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000477 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000478 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200479 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200480 if (!copy)
481 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000482 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000483 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000484 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000485 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000486 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000487
488#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000489 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000490 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000491 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100492#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000493
494#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000495 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000496 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000497 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100498#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000499
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000500 continue;
501 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000502 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100503 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000504 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000505 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000506 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000507 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000508 return;
509}
510
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000511#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000512static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000513decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000514{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000515 unsigned long addr;
516 unsigned int i, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000517
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000518 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
519 return;
520
521 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
522 addr = tcp->u_arg[1];
523 tcp->u_nargs = sysent[tcp->scno].nargs;
524 size = personality_wordsize[current_personality];
525 for (i = 0; i < tcp->u_nargs; ++i) {
526 if (size == sizeof(int)) {
527 unsigned int arg;
528 if (umove(tcp, addr, &arg) < 0)
529 arg = 0;
530 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000531 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000532 else {
533 unsigned long arg;
534 if (umove(tcp, addr, &arg) < 0)
535 arg = 0;
536 tcp->u_arg[i] = arg;
537 }
538 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000539 }
540}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000541#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400542
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000543#ifdef SYS_ipc_subcall
544static void
545decode_ipc_subcall(struct tcb *tcp)
546{
547 unsigned int i;
548
549 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
550 return;
551
552 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
553 tcp->u_nargs = sysent[tcp->scno].nargs;
554 for (i = 0; i < tcp->u_nargs; i++)
555 tcp->u_arg[i] = tcp->u_arg[i + 1];
556}
557#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000558
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200559int
560printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000561{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200562 if (entering(tcp)) {
563 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000564
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200565 for (i = 0; i < tcp->u_nargs; i++)
566 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
567 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000568 return 0;
569}
570
Denys Vlasenko72879c62012-02-27 14:18:02 +0100571int
572printargs_lu(struct tcb *tcp)
573{
574 if (entering(tcp)) {
575 int i;
576
577 for (i = 0; i < tcp->u_nargs; i++)
578 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
579 }
580 return 0;
581}
582
583int
584printargs_ld(struct tcb *tcp)
585{
586 if (entering(tcp)) {
587 int i;
588
589 for (i = 0; i < tcp->u_nargs; i++)
590 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
591 }
592 return 0;
593}
594
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200595long
596getrval2(struct tcb *tcp)
597{
598 long val = -1;
599
Denys Vlasenko523635f2012-02-25 02:44:25 +0100600#if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200601 struct pt_regs regs;
602 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
603 return -1;
604 val = regs.u_regs[U_REG_O1];
605#elif defined(SH)
606 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
607 return -1;
608#elif defined(IA64)
609 if (upeek(tcp, PT_R9, &val) < 0)
610 return -1;
611#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200612
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200613 return val;
614}
615
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200616int
617is_restart_error(struct tcb *tcp)
618{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200619 switch (tcp->u_error) {
620 case ERESTARTSYS:
621 case ERESTARTNOINTR:
622 case ERESTARTNOHAND:
623 case ERESTART_RESTARTBLOCK:
624 return 1;
625 default:
626 break;
627 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200628 return 0;
629}
630
Denys Vlasenko523635f2012-02-25 02:44:25 +0100631#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100632struct pt_regs i386_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100633#elif defined(X86_64)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100634/*
635 * On 32 bits, pt_regs and user_regs_struct are the same,
636 * but on 64 bits, user_regs_struct has six more fields:
637 * fs_base, gs_base, ds, es, fs, gs.
638 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
639 */
640static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100641#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200642long r8, r10, psr; /* TODO: make static? */
643long ia32 = 0; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100644#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +0200645static long result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100646#elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200647static long d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100648#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200649static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100650#elif defined(ARM)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200651static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100652#elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200653static long r0;
654static long a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100655#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200656static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100657#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200658static struct pt_regs regs;
659static unsigned long trap;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100660#elif defined(LINUX_MIPSN32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200661static long long a3;
662static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100663#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200664static long a3;
665static long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100666#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200667static long gpr2;
668static long pc;
669static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100670#elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200671static long r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100672#elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200673static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100674#elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200675static long r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100676#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200677static long r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100678#elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200679static long r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100680#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000681
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200682/* Returns:
683 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
684 * 1: ok, continue in trace_syscall().
685 * other: error, trace_syscall() should print error indicator
686 * ("????" etc) and bail out.
687 */
Denys Vlasenko9a36ae52011-08-24 16:47:32 +0200688static
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000689int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200690get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000691{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000692 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000693
Denys Vlasenko523635f2012-02-25 02:44:25 +0100694#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000695 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200696 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000697
698 if (syscall_mode != -ENOSYS) {
699 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000700 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000701 */
702 scno = syscall_mode;
703 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000704 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000705 * Old style of "passing" the scno via the SVC instruction.
706 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000707 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200708 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200709 static const int gpr_offset[16] = {
710 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
711 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
712 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
713 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
714 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000715
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000716 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000717 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000718 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000719 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000720 if (errno) {
721 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000722 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000723 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000724
725 /*
726 * We have to check if the SVC got executed directly or via an
727 * EXECUTE instruction. In case of EXECUTE it is necessary to do
728 * instruction decoding to derive the system call number.
729 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
730 * so that this doesn't work if a SVC opcode is part of an EXECUTE
731 * opcode. Since there is no way to find out the opcode size this
732 * is the best we can do...
733 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000734 if ((opcode & 0xff00) == 0x0a00) {
735 /* SVC opcode */
736 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000737 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000738 else {
739 /* SVC got executed by EXECUTE instruction */
740
741 /*
742 * Do instruction decoding of EXECUTE. If you really want to
743 * understand this, read the Principles of Operations.
744 */
745 svc_addr = (void *) (opcode & 0xfff);
746
747 tmp = 0;
748 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000749 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000750 return -1;
751 svc_addr += tmp;
752
753 tmp = 0;
754 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000755 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000756 return -1;
757 svc_addr += tmp;
758
Denys Vlasenkofb036672009-01-23 16:30:26 +0000759 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000760 if (errno)
761 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100762# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000763 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100764# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000765 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100766# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000767 tmp = 0;
768 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000769 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000770 return -1;
771
772 scno = (scno | tmp) & 0xff;
773 }
774 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100775#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000776 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000777 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100778# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200779 /* TODO: speed up strace by not doing this at every syscall.
780 * We only need to do it after execve.
781 */
782 int currpers;
783 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200784
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200785 /* Check for 64/32 bit mode. */
786 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
787 return -1;
788 /* SF is bit 0 of MSR */
789 if (val < 0)
790 currpers = 0;
791 else
792 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000793 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100794# endif
795#elif defined(AVR32)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200796 /* Read complete register set in one go. */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000797 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
798 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200799 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100800#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000801 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000802 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100803#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200804 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000805 return -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200806 scno = i386_regs.orig_eax;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100807#elif defined(X86_64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200808 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200809 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
810 return -1;
811 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +0000812
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200813 /* Check CS register value. On x86-64 linux it is:
814 * 0x33 for long mode (64 bit)
815 * 0x23 for compatibility mode (32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200816 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200817 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200818 case 0x23: currpers = 1; break;
819 case 0x33: currpers = 0; break;
820 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200821 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200822 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200823 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200824 currpers = current_personality;
825 break;
826 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100827# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200828 /* This version analyzes the opcode of a syscall instruction.
829 * (int 0x80 on i386 vs. syscall on x86-64)
830 * It works, but is too complicated.
831 */
832 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +0000833
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200834 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +0000835
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200836 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
837 rip -= 2;
838 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +0000839
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200840 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200841 if (errno)
842 fprintf(stderr, "ptrace_peektext failed: %s\n",
843 strerror(errno));
844 switch (call & 0xffff) {
845 /* x86-64: syscall = 0x0f 0x05 */
846 case 0x050f: currpers = 0; break;
847 /* i386: int 0x80 = 0xcd 0x80 */
848 case 0x80cd: currpers = 1; break;
849 default:
850 currpers = current_personality;
851 fprintf(stderr,
852 "Unknown syscall opcode (0x%04X) while "
853 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200854 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200855 break;
856 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100857# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000858 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100859#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000860# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200861 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000862 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200863 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200864 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200865 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000866 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200867 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000868 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200869 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100870#elif defined(ARM)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200871 /* Read complete register set in one go. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000872 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +0000873 return -1;
874
875 /*
876 * We only need to grab the syscall number on syscall entry.
877 */
878 if (regs.ARM_ip == 0) {
879 /*
880 * Note: we only deal with only 32-bit CPUs here.
881 */
882 if (regs.ARM_cpsr & 0x20) {
883 /*
884 * Get the Thumb-mode system call number
885 */
886 scno = regs.ARM_r7;
887 } else {
888 /*
889 * Get the ARM-mode system call number
890 */
891 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000892 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +0000893 if (errno)
894 return -1;
895
Roland McGrathf691bd22006-04-25 07:34:41 +0000896 /* Handle the EABI syscall convention. We do not
897 bother converting structures between the two
898 ABIs, but basic functionality should work even
899 if strace and the traced program have different
900 ABIs. */
901 if (scno == 0xef000000) {
902 scno = regs.ARM_r7;
903 } else {
904 if ((scno & 0x0ff00000) != 0x0f900000) {
905 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
906 scno);
907 return -1;
908 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000909
Roland McGrathf691bd22006-04-25 07:34:41 +0000910 /*
911 * Fixup the syscall number
912 */
913 scno &= 0x000fffff;
914 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000915 }
Roland McGrath56703312008-05-20 01:35:55 +0000916 if (scno & 0x0f0000) {
917 /*
918 * Handle ARM specific syscall
919 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000920 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +0000921 scno &= 0x0000ffff;
922 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000923 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +0000924
Roland McGrath0f87c492003-06-03 23:29:04 +0000925 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200926 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
927 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000928 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100929#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000930 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000931 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100932#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +0000933 unsigned long long regs[38];
934
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200935 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +0000936 return -1;
937 a3 = regs[REG_A3];
938 r2 = regs[REG_V0];
939
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200940 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200941 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200942 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100943 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200944 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000945 return 0;
946 }
Roland McGrath542c2c62008-05-20 01:11:56 +0000947 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100948#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000949 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000950 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200951 if (upeek(tcp, REG_V0, &scno) < 0)
952 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000953
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200954 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200955 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100956 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200957 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000958 return 0;
959 }
Wichert Akkermanf90da011999-10-31 21:15:38 +0000960 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100961#elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000962 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000963 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200964 if (upeek(tcp, REG_R0, &scno) < 0)
965 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000966
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200967 /*
968 * Do some sanity checks to figure out if it's
969 * really a syscall entry
970 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200971 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200972 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100973 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200974 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000975 return 0;
976 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000977 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100978#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000979 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000980 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000981 return -1;
982
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200983 /* Disassemble the syscall trap. */
984 /* Retrieve the syscall trap instruction. */
985 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100986# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200987 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
988 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100989# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200990 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100991# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200992 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +0000993 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200994
995 /* Disassemble the trap to see what personality to use. */
996 switch (trap) {
997 case 0x91d02010:
998 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000999 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001000 break;
1001 case 0x91d0206d:
1002 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001003 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001004 break;
1005 case 0x91d02000:
1006 /* SunOS syscall trap. (pers 1) */
1007 fprintf(stderr, "syscall: SunOS no support\n");
1008 return -1;
1009 case 0x91d02008:
1010 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001011 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001012 break;
1013 case 0x91d02009:
1014 /* NetBSD/FreeBSD syscall trap. */
1015 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1016 return -1;
1017 case 0x91d02027:
1018 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001019 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001020 break;
1021 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001022# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001023 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001024# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001025 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001026# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001027 return -1;
1028 }
1029
1030 /* Extract the system call number from the registers. */
1031 if (trap == 0x91d02027)
1032 scno = 156;
1033 else
1034 scno = regs.u_regs[U_REG_G1];
1035 if (scno == 0) {
1036 scno = regs.u_regs[U_REG_O0];
1037 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1038 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001039#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001040 if (upeek(tcp, PT_GR20, &scno) < 0)
1041 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001042#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001043 /*
1044 * In the new syscall ABI, the system call number is in R3.
1045 */
1046 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1047 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001048
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001049 if (scno < 0) {
1050 /* Odd as it may seem, a glibc bug has been known to cause
1051 glibc to issue bogus negative syscall numbers. So for
1052 our purposes, make strace print what it *should* have been */
1053 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001054 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001055 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001056 "Detected glibc bug: bogus system call"
1057 " number = %ld, correcting to %ld\n",
1058 scno,
1059 correct_scno);
1060 scno = correct_scno;
1061 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001062#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001063 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001064 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001065 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001066#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001067 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1068 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001069#elif defined(TILE)
Chris Metcalfc8c66982009-12-28 10:00:15 -05001070 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1071 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001072#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001073 if (upeek(tcp, 0, &scno) < 0)
1074 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001075#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001076
Denys Vlasenko523635f2012-02-25 02:44:25 +01001077#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001078 /* new syscall ABI returns result in R0 */
1079 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1080 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001081#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001082 /* ABI defines result returned in r9 */
1083 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1084 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001085#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001086
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001087 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001088 return 1;
1089}
1090
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001091/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001092 * Returns:
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001093 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
Roland McGratheb9e2e82009-06-02 16:49:22 -07001094 * 1: ok, continue in trace_syscall().
1095 * other: error, trace_syscall() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001096 * ("????" etc) and bail out.
1097 */
Roland McGratha4d48532005-06-08 20:45:28 +00001098static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001099syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001100{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001101 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001102#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001103 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001104 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001105 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1106 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001107 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001108#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001109 {
1110 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001111 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001112 rax = (int)rax; /* sign extend from 32 bits */
1113 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001114 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001115 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1116 return 0;
1117 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001118 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001119#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001120 /* TODO: we already fetched PT_GPR2 in get_scno
1121 * and stored it in syscall_mode, reuse it here
1122 * instead of re-fetching?
1123 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001124 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001125 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001126 if (syscall_mode != -ENOSYS)
1127 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001128 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001129 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001130 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001131 return 0;
1132 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001133#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001134 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001135 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001136 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001137 if (d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001138 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001139 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001140 return 0;
1141 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001142#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001143 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001144 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001145 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001146 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001147 if (ia32 && r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001148 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001149 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001150 return 0;
1151 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001152#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001153 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001154 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001155 if (r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001156 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001157 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001158 return 0;
1159 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001160#elif defined(MICROBLAZE)
1161 if (upeek(tcp, 3 * 4, &r3) < 0)
1162 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001163 if (r3 != -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 (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001166 return 0;
1167 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001168#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001169 return 1;
1170}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001171
Denys Vlasenko146b9442012-03-18 22:10:48 +01001172static void
1173internal_fork(struct tcb *tcp)
1174{
1175#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1176# define ARG_FLAGS 1
1177#else
1178# define ARG_FLAGS 0
1179#endif
1180#ifndef CLONE_UNTRACED
1181# define CLONE_UNTRACED 0x00800000
1182#endif
1183 if ((ptrace_setoptions
1184 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1185 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1186 return;
1187
1188 if (!followfork)
1189 return;
1190
1191 if (entering(tcp)) {
1192 /*
1193 * We won't see the new child if clone is called with
1194 * CLONE_UNTRACED, so we keep the same logic with that option
1195 * and don't trace it.
1196 */
1197 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1198 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1199 return;
1200 setbpt(tcp);
1201 } else {
1202 if (tcp->flags & TCB_BPTSET)
1203 clearbpt(tcp);
1204 }
1205}
1206
1207#if defined(TCB_WAITEXECVE)
1208static void
1209internal_exec(struct tcb *tcp)
1210{
1211 /* Maybe we have post-execve SIGTRAP suppressed? */
1212 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1213 return; /* yes, no need to do anything */
1214
1215 if (exiting(tcp) && syserror(tcp))
1216 /* Error in execve, no post-execve SIGTRAP expected */
1217 tcp->flags &= ~TCB_WAITEXECVE;
1218 else
1219 tcp->flags |= TCB_WAITEXECVE;
1220}
1221#endif
1222
1223static void
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001224internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001225{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001226 /*
1227 * We must always trace a few critical system calls in order to
1228 * correctly support following forks in the presence of tracing
1229 * qualifiers.
1230 */
1231 int (*func)();
1232
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001233 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001234 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001235
1236 func = sysent[tcp->scno].sys_func;
1237
1238 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001239 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001240 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001241 ) {
1242 internal_fork(tcp);
1243 return;
1244 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001245
Denys Vlasenko84703742012-02-25 02:38:52 +01001246#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001247 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001248# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001249 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001250# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001251 ) {
1252 internal_exec(tcp);
1253 return;
1254 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001255#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001256}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001257
Roland McGratha4d48532005-06-08 20:45:28 +00001258static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001259syscall_enter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001260{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001261 int i, nargs;
1262
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001263 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001264 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001265 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001266 nargs = tcp->u_nargs = MAX_ARGS;
1267
Denys Vlasenko523635f2012-02-25 02:44:25 +01001268#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001269 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001270 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1271 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001272#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001273 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001274 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1275 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001276#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001277 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001278 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001279 long rbs_end;
1280 /* be backwards compatible with kernel < 2.4.4... */
1281# ifndef PT_RBS_END
1282# define PT_RBS_END PT_AR_BSP
1283# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001284
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001285 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1286 return -1;
1287 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001288 return -1;
1289
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001290 sof = (cfm >> 0) & 0x7f;
1291 sol = (cfm >> 7) & 0x7f;
1292 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1293
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001294 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001295 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1296 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1297 return -1;
1298 }
1299 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001300 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1301 PT_R9 /* ECX = out1 */,
1302 PT_R10 /* EDX = out2 */,
1303 PT_R14 /* ESI = out3 */,
1304 PT_R15 /* EDI = out4 */,
1305 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001306
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001307 for (i = 0; i < nargs; ++i) {
1308 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1309 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001310 /* truncate away IVE sign-extension */
1311 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001312 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001313 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001314#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001315 /* N32 and N64 both use up to six registers. */
1316 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001317
1318 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1319 return -1;
1320
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001321 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001322 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001323# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001324 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001325# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001326 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001327#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001328 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001329 long sp;
1330
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001331 if (upeek(tcp, REG_SP, &sp) < 0)
1332 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001333 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001334 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1335 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001336 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001337 (char *)(tcp->u_arg + 4));
1338 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001339 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001340 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001341 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001342 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001343#elif defined(POWERPC)
1344# ifndef PT_ORIG_R3
1345# define PT_ORIG_R3 34
1346# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001347 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001348 if (upeek(tcp, (i==0) ?
1349 (sizeof(unsigned long) * PT_ORIG_R3) :
1350 ((i+PT_R3) * sizeof(unsigned long)),
1351 &tcp->u_arg[i]) < 0)
1352 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001353 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001354#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001355 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001356 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001357#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001358 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001359 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1360 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001361#elif defined(ARM)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001362 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001363 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001364#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001365 (void)i;
1366 (void)nargs;
1367 tcp->u_arg[0] = regs.r12;
1368 tcp->u_arg[1] = regs.r11;
1369 tcp->u_arg[2] = regs.r10;
1370 tcp->u_arg[3] = regs.r9;
1371 tcp->u_arg[4] = regs.r5;
1372 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001373#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001374 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 +02001375
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001376 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001377 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1378 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001379#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001380 static const int syscall_regs[MAX_ARGS] = {
1381 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1382 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001383 };
1384
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001385 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001386 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001387 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001388#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001389 int i;
1390 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001391 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001392
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001393 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001394 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1395 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001396#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001397 (void)i;
1398 (void)nargs;
1399 if (current_personality == 0) { /* x86-64 ABI */
1400 tcp->u_arg[0] = x86_64_regs.rdi;
1401 tcp->u_arg[1] = x86_64_regs.rsi;
1402 tcp->u_arg[2] = x86_64_regs.rdx;
1403 tcp->u_arg[3] = x86_64_regs.r10;
1404 tcp->u_arg[4] = x86_64_regs.r8;
1405 tcp->u_arg[5] = x86_64_regs.r9;
1406 } else { /* i386 ABI */
1407 /* Sign-extend lower 32 bits */
1408 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1409 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1410 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1411 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1412 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1413 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1414 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001415#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001416 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001417 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1418 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001419#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001420 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001421 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001422 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001423 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001424
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001425 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001426 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1427 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001428#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001429 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001430 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1431 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001432#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001433 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001434 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1435 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001436#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001437 (void)i;
1438 (void)nargs;
1439 tcp->u_arg[0] = i386_regs.ebx;
1440 tcp->u_arg[1] = i386_regs.ecx;
1441 tcp->u_arg[2] = i386_regs.edx;
1442 tcp->u_arg[3] = i386_regs.esi;
1443 tcp->u_arg[4] = i386_regs.edi;
1444 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001445#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001446 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001447 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1448 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001449#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001450 return 1;
1451}
1452
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001453static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001454trace_syscall_entering(struct tcb *tcp)
1455{
1456 int res, scno_good;
1457
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001458#if defined TCB_WAITEXECVE
1459 if (tcp->flags & TCB_WAITEXECVE) {
1460 /* This is the post-execve SIGTRAP. */
1461 tcp->flags &= ~TCB_WAITEXECVE;
1462 return 0;
1463 }
1464#endif
1465
Denys Vlasenko06602d92011-08-24 17:53:52 +02001466 scno_good = res = get_scno(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001467 if (res == 0)
1468 return res;
1469 if (res == 1)
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001470 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001471 if (res == 0)
1472 return res;
1473 if (res == 1)
1474 res = syscall_enter(tcp);
1475 if (res == 0)
1476 return res;
1477
1478 if (res != 1) {
1479 printleader(tcp);
1480 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001481 if (scno_good != 1)
1482 tprintf("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001483 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001484 tprintf("syscall_%lu(", tcp->scno);
1485 else
1486 tprintf("%s(", sysent[tcp->scno].sys_name);
1487 /*
1488 * " <unavailable>" will be added later by the code which
1489 * detects ptrace errors.
1490 */
1491 goto ret;
1492 }
1493
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001494#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1495 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001496# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001497 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001498 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001499 break;
1500 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001501# endif
1502# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001503 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001504 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001505 break;
1506 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001507# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001508 break;
1509 }
1510#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1511
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001512 internal_syscall(tcp);
1513
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001514 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001515 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1516 (tracing_paths && !pathtrace_match(tcp))) {
1517 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1518 return 0;
1519 }
1520
1521 tcp->flags &= ~TCB_FILTERED;
1522
1523 if (cflag == CFLAG_ONLY_STATS) {
1524 res = 0;
1525 goto ret;
1526 }
1527
1528 printleader(tcp);
1529 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001530 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001531 tprintf("syscall_%lu(", tcp->scno);
1532 else
1533 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001534 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001535 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1536 sysent[tcp->scno].sys_func != sys_exit))
1537 res = printargs(tcp);
1538 else
1539 res = (*sysent[tcp->scno].sys_func)(tcp);
1540
1541 if (fflush(tcp->outf) == EOF)
1542 return -1;
1543 ret:
1544 tcp->flags |= TCB_INSYSCALL;
1545 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001546 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001547 gettimeofday(&tcp->etime, NULL);
1548 return res;
1549}
1550
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001551/* Returns:
1552 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1553 * 1: ok, continue in trace_syscall().
1554 * other: error, trace_syscall() should print error indicator
1555 * ("????" etc) and bail out.
1556 */
1557static int
1558get_syscall_result(struct tcb *tcp)
1559{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001560#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001561 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1562 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001563#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001564# define SO_MASK 0x10000000
1565 {
1566 long flags;
1567 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1568 return -1;
1569 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &result) < 0)
1570 return -1;
1571 if (flags & SO_MASK)
1572 result = -result;
1573 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001574#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001575 /* Read complete register set in one go. */
1576 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1577 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001578#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001579 if (upeek(tcp, PT_R0, &r0) < 0)
1580 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001581#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001582 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001583 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001584#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001585 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001586 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001587#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001588# define IA64_PSR_IS ((long)1 << 34)
1589 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1590 ia32 = (psr & IA64_PSR_IS) != 0;
1591 if (upeek(tcp, PT_R8, &r8) < 0)
1592 return -1;
1593 if (upeek(tcp, PT_R10, &r10) < 0)
1594 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001595#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001596 /* Read complete register set in one go. */
1597 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1598 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001599#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001600 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1601 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001602#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001603 unsigned long long regs[38];
1604
1605 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1606 return -1;
1607 a3 = regs[REG_A3];
1608 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001609#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001610 if (upeek(tcp, REG_A3, &a3) < 0)
1611 return -1;
1612 if (upeek(tcp, REG_V0, &r2) < 0)
1613 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001614#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001615 if (upeek(tcp, REG_A3, &a3) < 0)
1616 return -1;
1617 if (upeek(tcp, REG_R0, &r0) < 0)
1618 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001619#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001620 /* Everything we need is in the current register set. */
1621 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1622 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001623#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001624 if (upeek(tcp, PT_GR28, &r28) < 0)
1625 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001626#elif defined(SH)
1627#elif defined(SH64)
1628#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001629 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1630 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001631#elif defined(TILE)
1632#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001633 if (upeek(tcp, 3 * 4, &r3) < 0)
1634 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001635#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001636
Denys Vlasenko523635f2012-02-25 02:44:25 +01001637#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001638 /* new syscall ABI returns result in R0 */
1639 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1640 return -1;
1641#elif defined(SH64)
1642 /* ABI defines result returned in r9 */
1643 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1644 return -1;
1645#endif
1646
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001647 return 1;
1648}
1649
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001650/* Called at each syscall exit.
1651 * Returns:
1652 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1653 * 1: ok, continue in trace_syscall().
1654 * other: error, trace_syscall() should print error indicator
1655 * ("????" etc) and bail out.
1656 */
1657static int
1658syscall_fixup_on_sysexit(struct tcb *tcp)
1659{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001660#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001661 if (syscall_mode != -ENOSYS)
1662 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001663 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001664 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1665 /*
1666 * Return from execve.
1667 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1668 * flag set for the post-execve SIGTRAP to see and reset.
1669 */
1670 gpr2 = 0;
1671 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001672#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001673 return 1;
1674}
1675
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001676/*
1677 * Check the syscall return value register value for whether it is
1678 * a negated errno code indicating an error, or a success return value.
1679 */
1680static inline int
1681is_negated_errno(unsigned long int val)
1682{
1683 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001684#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001685 if (personality_wordsize[current_personality] < sizeof(val)) {
1686 val = (unsigned int) val;
1687 max = (unsigned int) max;
1688 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001689#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001690 return val > max;
1691}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001692
1693static int
1694get_error(struct tcb *tcp)
1695{
1696 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001697 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001698 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001699 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1700 check_errno = 0;
1701 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001702#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001703 if (check_errno && is_negated_errno(gpr2)) {
1704 tcp->u_rval = -1;
1705 u_error = -gpr2;
1706 }
1707 else {
1708 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001709 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001710#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001711 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001712 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001713 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001714 }
1715 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001716 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001717 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001718#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001719 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001720 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001721 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001722 }
1723 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001724 tcp->u_rval = x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001725 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001726#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001727 if (ia32) {
1728 int err;
1729
1730 err = (int)r8;
1731 if (check_errno && is_negated_errno(err)) {
1732 tcp->u_rval = -1;
1733 u_error = -err;
1734 }
1735 else {
1736 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001737 }
1738 } else {
1739 if (check_errno && r10) {
1740 tcp->u_rval = -1;
1741 u_error = r8;
1742 } else {
1743 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001744 }
1745 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001746#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001747 if (check_errno && a3) {
1748 tcp->u_rval = -1;
1749 u_error = r2;
1750 } else {
1751 tcp->u_rval = r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001752 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001753#elif defined(POWERPC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001754 if (check_errno && is_negated_errno(result)) {
1755 tcp->u_rval = -1;
1756 u_error = -result;
1757 }
1758 else {
1759 tcp->u_rval = result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001760 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001761#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001762 if (check_errno && is_negated_errno(d0)) {
1763 tcp->u_rval = -1;
1764 u_error = -d0;
1765 }
1766 else {
1767 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001768 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001769#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001770 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1771 tcp->u_rval = -1;
1772 u_error = -regs.ARM_r0;
1773 }
1774 else {
1775 tcp->u_rval = regs.ARM_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001776 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001777#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001778 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1779 tcp->u_rval = -1;
1780 u_error = -regs.r12;
1781 }
1782 else {
1783 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001784 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001785#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001786 if (check_errno && is_negated_errno(r0)) {
1787 tcp->u_rval = -1;
1788 u_error = -r0;
1789 } else {
1790 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001791 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001792#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001793 if (check_errno && a3) {
1794 tcp->u_rval = -1;
1795 u_error = r0;
1796 }
1797 else {
1798 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001799 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001800#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001801 if (check_errno && regs.psr & PSR_C) {
1802 tcp->u_rval = -1;
1803 u_error = regs.u_regs[U_REG_O0];
1804 }
1805 else {
1806 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001807 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001808#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001809 if (check_errno && regs.tstate & 0x1100000000UL) {
1810 tcp->u_rval = -1;
1811 u_error = regs.u_regs[U_REG_O0];
1812 }
1813 else {
1814 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001815 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001816#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001817 if (check_errno && is_negated_errno(r28)) {
1818 tcp->u_rval = -1;
1819 u_error = -r28;
1820 }
1821 else {
1822 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001823 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001824#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001825 if (check_errno && is_negated_errno(r0)) {
1826 tcp->u_rval = -1;
1827 u_error = -r0;
1828 }
1829 else {
1830 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001831 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001832#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001833 if (check_errno && is_negated_errno(r9)) {
1834 tcp->u_rval = -1;
1835 u_error = -r9;
1836 }
1837 else {
1838 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001839 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001840#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001841 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1842 tcp->u_rval = -1;
1843 u_error = -r10;
1844 }
1845 else {
1846 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001847 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001848#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001849 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001850 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1851 return -1;
1852 if (check_errno && rval < 0 && rval > -nerrnos) {
1853 tcp->u_rval = -1;
1854 u_error = -rval;
1855 }
1856 else {
1857 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001858 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001859#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001860 if (check_errno && is_negated_errno(r3)) {
1861 tcp->u_rval = -1;
1862 u_error = -r3;
1863 }
1864 else {
1865 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001866 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001867#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001868 tcp->u_error = u_error;
1869 return 1;
1870}
1871
1872static void
1873dumpio(struct tcb *tcp)
1874{
1875 if (syserror(tcp))
1876 return;
1877 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1878 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001879 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001880 return;
1881 if (sysent[tcp->scno].sys_func == printargs)
1882 return;
1883 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1884 if (sysent[tcp->scno].sys_func == sys_read ||
1885 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001886 sysent[tcp->scno].sys_func == sys_recv ||
1887 sysent[tcp->scno].sys_func == sys_recvfrom)
1888 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1889 else if (sysent[tcp->scno].sys_func == sys_readv)
1890 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1891 return;
1892 }
1893 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1894 if (sysent[tcp->scno].sys_func == sys_write ||
1895 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001896 sysent[tcp->scno].sys_func == sys_send ||
1897 sysent[tcp->scno].sys_func == sys_sendto)
1898 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1899 else if (sysent[tcp->scno].sys_func == sys_writev)
1900 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1901 return;
1902 }
1903}
1904
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001905static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001906trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001907{
1908 int sys_res;
1909 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001910 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001911 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001912
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001913 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001914 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001915 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001916
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001917#if SUPPORTED_PERSONALITIES > 1
1918 update_personality(tcp, tcp->currpers);
1919#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001920 res = get_syscall_result(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001921 if (res == 0)
1922 return res;
1923 if (res == 1)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001924 res = syscall_fixup_on_sysexit(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001925 if (res == 0)
1926 return res;
1927 if (res == 1)
1928 res = get_error(tcp);
1929 if (res == 0)
1930 return res;
1931 if (res == 1)
1932 internal_syscall(tcp);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001933
Grant Edwards8a082772011-04-07 20:25:40 +00001934 if (res == 1 && filtered(tcp)) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001935 goto ret;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001936 }
1937
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001938 /* TODO: TCB_REPRINT is probably not necessary:
1939 * we can determine whether reprinting is needed
1940 * by examining printing_tcp. Something like:
1941 * if not in -ff mode, and printing_tcp != tcp,
1942 * then the log is not currenlty ends with *our*
1943 * syscall entry output, but with something else,
1944 * and we need to reprint.
1945 * If we'd implement this, printing_tcp = tcp
1946 * assignments in code below can be made more logical.
1947 */
1948
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001949 if (tcp->flags & TCB_REPRINT) {
1950 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001951 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001952 tprintf("<... syscall_%lu resumed> ", tcp->scno);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001953 else
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001954 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001955 }
1956
1957 if (cflag) {
1958 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02001959 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02001960 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001961 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001962 }
1963 }
1964
1965 if (res != 1) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001966 printing_tcp = tcp;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001967 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001968 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01001969 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001970 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001971 tcp->flags &= ~TCB_INSYSCALL;
1972 return res;
1973 }
1974
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001975 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001976 || (qual_flags[tcp->scno] & QUAL_RAW)) {
1977 printing_tcp = tcp;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001978 sys_res = printargs(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001979 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001980 /* FIXME: not_failing_only (IOW, option -z) is broken:
1981 * failure of syscall is known only after syscall return.
1982 * Thus we end up with something like this on, say, ENOENT:
1983 * open("doesnt_exist", O_RDONLY <unfinished ...>
1984 * {next syscall decode}
1985 * whereas the intended result is that open(...) line
1986 * is not shown at all.
1987 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001988 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02001989 goto ret; /* ignore failed syscalls */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001990 printing_tcp = tcp;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001991 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
1992 }
1993
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001994 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001995 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02001996 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001997 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001998 qual_flags[tcp->scno] & QUAL_RAW) {
1999 if (u_error)
2000 tprintf("= -1 (errno %ld)", u_error);
2001 else
2002 tprintf("= %#lx", tcp->u_rval);
2003 }
2004 else if (!(sys_res & RVAL_NONE) && u_error) {
2005 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002006 /* Blocked signals do not interrupt any syscalls.
2007 * In this case syscalls don't return ERESTARTfoo codes.
2008 *
2009 * Deadly signals set to SIG_DFL interrupt syscalls
2010 * and kill the process regardless of which of the codes below
2011 * is returned by the interrupted syscall.
2012 * In some cases, kernel forces a kernel-generated deadly
2013 * signal to be unblocked and set to SIG_DFL (and thus cause
2014 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2015 * or SIGILL. (The alternative is to leave process spinning
2016 * forever on the faulty instruction - not useful).
2017 *
2018 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2019 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2020 * but kernel will always restart them.
2021 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002022 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002023 /* Most common type of signal-interrupted syscall exit code.
2024 * The system call will be restarted with the same arguments
2025 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2026 */
2027 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002028 break;
2029 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002030 /* Rare. For example, fork() returns this if interrupted.
2031 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2032 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002033 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002034 break;
2035 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002036 /* pause(), rt_sigsuspend() etc use this code.
2037 * SA_RESTART is ignored (assumed not set):
2038 * syscall won't restart (will return EINTR instead)
2039 * even after signal with SA_RESTART set.
2040 * However, after SIG_IGN or SIG_DFL signal it will.
2041 */
2042 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002043 break;
2044 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002045 /* Syscalls like nanosleep(), poll() which can't be
2046 * restarted with their original arguments use this
2047 * code. Kernel will execute restart_syscall() instead,
2048 * which changes arguments before restarting syscall.
2049 * SA_RESTART is ignored (assumed not set) similarly
2050 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2051 * since restart data is saved in "restart block"
2052 * in task struct, and if signal handler uses a syscall
2053 * which in turn saves another such restart block,
2054 * old data is lost and restart becomes impossible)
2055 */
2056 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002057 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002058 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002059 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002060 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002061 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002062 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002063 strerror(u_error));
2064 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002065 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002066 strerror(u_error));
2067 break;
2068 }
2069 if ((sys_res & RVAL_STR) && tcp->auxstr)
2070 tprintf(" (%s)", tcp->auxstr);
2071 }
2072 else {
2073 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002074 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002075 else {
2076 switch (sys_res & RVAL_MASK) {
2077 case RVAL_HEX:
2078 tprintf("= %#lx", tcp->u_rval);
2079 break;
2080 case RVAL_OCTAL:
2081 tprintf("= %#lo", tcp->u_rval);
2082 break;
2083 case RVAL_UDECIMAL:
2084 tprintf("= %lu", tcp->u_rval);
2085 break;
2086 case RVAL_DECIMAL:
2087 tprintf("= %ld", tcp->u_rval);
2088 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002089 default:
2090 fprintf(stderr,
2091 "invalid rval format\n");
2092 break;
2093 }
2094 }
2095 if ((sys_res & RVAL_STR) && tcp->auxstr)
2096 tprintf(" (%s)", tcp->auxstr);
2097 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002098 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002099 tv_sub(&tv, &tv, &tcp->etime);
2100 tprintf(" <%ld.%06ld>",
2101 (long) tv.tv_sec, (long) tv.tv_usec);
2102 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002103 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002104 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002105 line_ended();
2106
Denys Vlasenko3b738812011-08-22 02:06:35 +02002107 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002108 tcp->flags &= ~TCB_INSYSCALL;
2109 return 0;
2110}
2111
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002112int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002113trace_syscall(struct tcb *tcp)
2114{
2115 return exiting(tcp) ?
2116 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2117}