blob: 52d742f7e324f20bf82ee288a8c7fd13c0a5ebbf [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 Vlasenko9fd4f962012-03-19 09:36:42 +0100186const struct sysent *sysent = sysent0;
187const char *const *errnoent = errnoent0;
188const char *const *signalent = signalent0;
189const struct ioctlent *ioctlent = ioctlent0;
190unsigned nsyscalls = nsyscalls0;
191unsigned nerrnos = nerrnos0;
192unsigned nsignals = nsignals0;
193unsigned nioctlents = nioctlents0;
194int *qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000195
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100196#if SUPPORTED_PERSONALITIES > 1
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000197int current_personality;
198
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000199const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
200 PERSONALITY0_WORDSIZE,
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000201 PERSONALITY1_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100202# if SUPPORTED_PERSONALITIES > 2
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000203 PERSONALITY2_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100204# endif
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200205};
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000206
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200207void
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000208set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000209{
210 switch (personality) {
211 case 0:
212 errnoent = errnoent0;
213 nerrnos = nerrnos0;
214 sysent = sysent0;
215 nsyscalls = nsyscalls0;
216 ioctlent = ioctlent0;
217 nioctlents = nioctlents0;
218 signalent = signalent0;
219 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000220 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000221 break;
222
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000223 case 1:
224 errnoent = errnoent1;
225 nerrnos = nerrnos1;
226 sysent = sysent1;
227 nsyscalls = nsyscalls1;
228 ioctlent = ioctlent1;
229 nioctlents = nioctlents1;
230 signalent = signalent1;
231 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000232 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000233 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000234
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100235# if SUPPORTED_PERSONALITIES >= 3
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000236 case 2:
237 errnoent = errnoent2;
238 nerrnos = nerrnos2;
239 sysent = sysent2;
240 nsyscalls = nsyscalls2;
241 ioctlent = ioctlent2;
242 nioctlents = nioctlents2;
243 signalent = signalent2;
244 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000245 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000246 break;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100247# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000248 }
249
250 current_personality = personality;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000251}
252
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000253static void
254update_personality(struct tcb *tcp, int personality)
255{
256 if (personality == current_personality)
257 return;
258 set_personality(personality);
259
260 if (personality == tcp->currpers)
261 return;
262 tcp->currpers = personality;
263
H.J. Lu35be5812012-04-16 13:00:01 +0200264# if defined(POWERPC64)
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000265 if (!qflag) {
266 static const char *const names[] = {"64 bit", "32 bit"};
267 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
268 tcp->pid, names[personality]);
269 }
H.J. Lu35be5812012-04-16 13:00:01 +0200270# elif defined(X86_64)
271 if (!qflag) {
272 static const char *const names[] = {"64 bit", "32 bit", "x32"};
273 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
274 tcp->pid, names[personality]);
275 }
H.J. Lu085e4282012-04-17 11:05:04 -0700276# elif defined(X32)
277 if (!qflag) {
278 static const char *const names[] = {"x32", "32 bit"};
279 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
280 tcp->pid, names[personality]);
281 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100282# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000283}
284#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000285
Roland McGrath9797ceb2002-12-30 10:23:00 +0000286static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000287
Roland McGrathe10e62a2004-09-04 04:20:43 +0000288static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000289 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000290 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000291 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000292 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000293} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000294 { QUAL_TRACE, "trace", qual_syscall, "system call" },
295 { QUAL_TRACE, "t", qual_syscall, "system call" },
296 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
297 { QUAL_ABBREV, "a", qual_syscall, "system call" },
298 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
299 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
300 { QUAL_RAW, "raw", qual_syscall, "system call" },
301 { QUAL_RAW, "x", qual_syscall, "system call" },
302 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
303 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
304 { QUAL_SIGNAL, "s", qual_signal, "signal" },
305 { QUAL_FAULT, "fault", qual_fault, "fault" },
306 { QUAL_FAULT, "faults", qual_fault, "fault" },
307 { QUAL_FAULT, "m", qual_fault, "fault" },
308 { QUAL_READ, "read", qual_desc, "descriptor" },
309 { QUAL_READ, "reads", qual_desc, "descriptor" },
310 { QUAL_READ, "r", qual_desc, "descriptor" },
311 { QUAL_WRITE, "write", qual_desc, "descriptor" },
312 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
313 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000314 { 0, NULL, NULL, NULL },
315};
316
Roland McGrath9797ceb2002-12-30 10:23:00 +0000317static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000318qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000319{
Roland McGrath138c6a32006-01-12 09:50:49 +0000320 if (pers == 0 || pers < 0) {
321 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000322 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000323 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000324 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000325 }
326
327#if SUPPORTED_PERSONALITIES >= 2
328 if (pers == 1 || pers < 0) {
329 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000330 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000331 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000332 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000333 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100334#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000335
336#if SUPPORTED_PERSONALITIES >= 3
337 if (pers == 2 || pers < 0) {
338 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000339 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000340 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000341 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000342 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100343#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000344}
345
346static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000347qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000348{
349 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000350 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000351
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100352 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000353 int i = string_to_uint(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000354 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000355 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000356 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000357 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000358 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000359 for (i = 0; i < nsyscalls0; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000360 if (sysent0[i].sys_name &&
361 strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000362 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000363 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000364 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000365
366#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000367 for (i = 0; i < nsyscalls1; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000368 if (sysent1[i].sys_name &&
369 strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000370 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000371 rc = 0;
372 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100373#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000374
375#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000376 for (i = 0; i < nsyscalls2; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000377 if (sysent2[i].sys_name &&
378 strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000379 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000380 rc = 0;
381 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100382#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000383
Roland McGrathfe6b3522005-02-02 04:40:11 +0000384 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000385}
386
387static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000388qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000389{
390 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000391
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100392 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000393 int signo = string_to_uint(s);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000394 if (signo < 0 || signo >= MAX_QUALS)
395 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000396 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000397 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000398 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000399 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000400 s += 3;
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100401 for (i = 0; i <= NSIG; i++) {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000402 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000403 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000404 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000405 }
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100406 }
Roland McGrath76421df2005-02-02 03:51:18 +0000407 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000408}
409
410static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000411qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000412{
413 return -1;
414}
415
416static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000417qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000418{
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100419 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000420 int desc = string_to_uint(s);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000421 if (desc < 0 || desc >= MAX_QUALS)
422 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000423 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000424 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000425 }
426 return -1;
427}
428
429static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000430lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000431{
432 if (strcmp(s, "file") == 0)
433 return TRACE_FILE;
434 if (strcmp(s, "ipc") == 0)
435 return TRACE_IPC;
436 if (strcmp(s, "network") == 0)
437 return TRACE_NETWORK;
438 if (strcmp(s, "process") == 0)
439 return TRACE_PROCESS;
440 if (strcmp(s, "signal") == 0)
441 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000442 if (strcmp(s, "desc") == 0)
443 return TRACE_DESC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000444 return -1;
445}
446
447void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000448qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000449{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000450 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000451 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000452 char *copy;
453 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000454 int i, n;
455
456 opt = &qual_options[0];
457 for (i = 0; (p = qual_options[i].option_name); i++) {
458 n = strlen(p);
459 if (strncmp(s, p, n) == 0 && s[n] == '=') {
460 opt = &qual_options[i];
461 s += n + 1;
462 break;
463 }
464 }
465 not = 0;
466 if (*s == '!') {
467 not = 1;
468 s++;
469 }
470 if (strcmp(s, "none") == 0) {
471 not = 1 - not;
472 s = "all";
473 }
474 if (strcmp(s, "all") == 0) {
475 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000476 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000477 }
478 return;
479 }
480 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000481 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000482 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200483 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200484 if (!copy)
485 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000486 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000487 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000488 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000489 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000490 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000491
492#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000493 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000494 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000495 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100496#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000497
498#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000499 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000500 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000501 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100502#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000503
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000504 continue;
505 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000506 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100507 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000508 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000509 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000510 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000511 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000512 return;
513}
514
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000515#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000516static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000517decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000518{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000519 unsigned long addr;
520 unsigned int i, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000521
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000522 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
523 return;
524
525 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
526 addr = tcp->u_arg[1];
527 tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100528 size = current_wordsize;
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000529 for (i = 0; i < tcp->u_nargs; ++i) {
530 if (size == sizeof(int)) {
531 unsigned int arg;
532 if (umove(tcp, addr, &arg) < 0)
533 arg = 0;
534 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000535 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000536 else {
537 unsigned long arg;
538 if (umove(tcp, addr, &arg) < 0)
539 arg = 0;
540 tcp->u_arg[i] = arg;
541 }
542 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000543 }
544}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000545#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400546
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000547#ifdef SYS_ipc_subcall
548static void
549decode_ipc_subcall(struct tcb *tcp)
550{
551 unsigned int i;
552
553 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
554 return;
555
556 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
557 tcp->u_nargs = sysent[tcp->scno].nargs;
558 for (i = 0; i < tcp->u_nargs; i++)
559 tcp->u_arg[i] = tcp->u_arg[i + 1];
560}
561#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000562
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200563int
564printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000565{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200566 if (entering(tcp)) {
567 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000568
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200569 for (i = 0; i < tcp->u_nargs; i++)
570 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
571 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000572 return 0;
573}
574
Denys Vlasenko72879c62012-02-27 14:18:02 +0100575int
576printargs_lu(struct tcb *tcp)
577{
578 if (entering(tcp)) {
579 int i;
580
581 for (i = 0; i < tcp->u_nargs; i++)
582 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
583 }
584 return 0;
585}
586
587int
588printargs_ld(struct tcb *tcp)
589{
590 if (entering(tcp)) {
591 int i;
592
593 for (i = 0; i < tcp->u_nargs; i++)
594 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
595 }
596 return 0;
597}
598
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200599long
600getrval2(struct tcb *tcp)
601{
602 long val = -1;
603
Denys Vlasenko523635f2012-02-25 02:44:25 +0100604#if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200605 struct pt_regs regs;
606 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
607 return -1;
608 val = regs.u_regs[U_REG_O1];
609#elif defined(SH)
610 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
611 return -1;
612#elif defined(IA64)
613 if (upeek(tcp, PT_R9, &val) < 0)
614 return -1;
615#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200616
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200617 return val;
618}
619
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200620int
621is_restart_error(struct tcb *tcp)
622{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200623 switch (tcp->u_error) {
624 case ERESTARTSYS:
625 case ERESTARTNOINTR:
626 case ERESTARTNOHAND:
627 case ERESTART_RESTARTBLOCK:
628 return 1;
629 default:
630 break;
631 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200632 return 0;
633}
634
Denys Vlasenko523635f2012-02-25 02:44:25 +0100635#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100636struct pt_regs i386_regs;
H.J. Lu35be5812012-04-16 13:00:01 +0200637#elif defined(X86_64) || defined(X32)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100638/*
639 * On 32 bits, pt_regs and user_regs_struct are the same,
640 * but on 64 bits, user_regs_struct has six more fields:
641 * fs_base, gs_base, ds, es, fs, gs.
642 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
643 */
644static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100645#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200646long r8, r10, psr; /* TODO: make static? */
647long ia32 = 0; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100648#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +0100649static long ppc_result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100650#elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200651static long d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100652#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200653static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100654#elif defined(ARM)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200655static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100656#elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200657static long r0;
658static long a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100659#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200660static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100661#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200662static struct pt_regs regs;
663static unsigned long trap;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100664#elif defined(LINUX_MIPSN32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200665static long long a3;
666static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100667#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200668static long a3;
669static long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100670#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200671static long gpr2;
672static long pc;
673static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100674#elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200675static long r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100676#elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200677static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100678#elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200679static long r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100680#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200681static long r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100682#elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200683static long r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100684#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000685
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200686/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100687 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
688 * 1: ok, continue in trace_syscall_entering().
689 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200690 * ("????" etc) and bail out.
691 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100692static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200693get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000694{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000695 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000696
Denys Vlasenko523635f2012-02-25 02:44:25 +0100697#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000698 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200699 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000700
701 if (syscall_mode != -ENOSYS) {
702 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000703 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000704 */
705 scno = syscall_mode;
706 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000707 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000708 * Old style of "passing" the scno via the SVC instruction.
709 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000710 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200711 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200712 static const int gpr_offset[16] = {
713 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
714 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
715 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
716 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
717 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000718
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000719 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000720 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000721 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000722 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000723 if (errno) {
724 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000725 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000726 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000727
728 /*
729 * We have to check if the SVC got executed directly or via an
730 * EXECUTE instruction. In case of EXECUTE it is necessary to do
731 * instruction decoding to derive the system call number.
732 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
733 * so that this doesn't work if a SVC opcode is part of an EXECUTE
734 * opcode. Since there is no way to find out the opcode size this
735 * is the best we can do...
736 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000737 if ((opcode & 0xff00) == 0x0a00) {
738 /* SVC opcode */
739 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000740 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000741 else {
742 /* SVC got executed by EXECUTE instruction */
743
744 /*
745 * Do instruction decoding of EXECUTE. If you really want to
746 * understand this, read the Principles of Operations.
747 */
748 svc_addr = (void *) (opcode & 0xfff);
749
750 tmp = 0;
751 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000752 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000753 return -1;
754 svc_addr += tmp;
755
756 tmp = 0;
757 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000758 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000759 return -1;
760 svc_addr += tmp;
761
Denys Vlasenkofb036672009-01-23 16:30:26 +0000762 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000763 if (errno)
764 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100765# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000766 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100767# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000768 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100769# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000770 tmp = 0;
771 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000772 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000773 return -1;
774
775 scno = (scno | tmp) & 0xff;
776 }
777 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100778#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000779 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000780 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100781# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200782 /* TODO: speed up strace by not doing this at every syscall.
783 * We only need to do it after execve.
784 */
785 int currpers;
786 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200787
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200788 /* Check for 64/32 bit mode. */
789 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
790 return -1;
791 /* SF is bit 0 of MSR */
792 if (val < 0)
793 currpers = 0;
794 else
795 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000796 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100797# endif
798#elif defined(AVR32)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200799 /* Read complete register set in one go. */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000800 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
801 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200802 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100803#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000804 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000805 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100806#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200807 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000808 return -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200809 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +0200810#elif defined(X86_64) || defined(X32)
811# ifndef __X32_SYSCALL_BIT
812# define __X32_SYSCALL_BIT 0x40000000
813# endif
814# ifndef __X32_SYSCALL_MASK
815# define __X32_SYSCALL_MASK __X32_SYSCALL_BIT
816# endif
817
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200818 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200819 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
820 return -1;
821 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +0000822
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200823 /* Check CS register value. On x86-64 linux it is:
824 * 0x33 for long mode (64 bit)
825 * 0x23 for compatibility mode (32 bit)
H.J. Lu35be5812012-04-16 13:00:01 +0200826 * Check DS register value. On x86-64 linux it is:
827 * 0x2b for x32 mode (x86-64 in 32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200828 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200829 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200830 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +0200831 case 0x33:
832 if (x86_64_regs.ds == 0x2b) {
833 currpers = 2;
834 scno &= ~__X32_SYSCALL_MASK;
835 } else
836 currpers = 0;
837 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200838 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200839 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200840 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200841 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200842 currpers = current_personality;
843 break;
844 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100845# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200846 /* This version analyzes the opcode of a syscall instruction.
847 * (int 0x80 on i386 vs. syscall on x86-64)
848 * It works, but is too complicated.
849 */
850 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +0000851
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200852 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +0000853
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200854 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
855 rip -= 2;
856 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +0000857
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200858 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200859 if (errno)
860 fprintf(stderr, "ptrace_peektext failed: %s\n",
861 strerror(errno));
862 switch (call & 0xffff) {
863 /* x86-64: syscall = 0x0f 0x05 */
864 case 0x050f: currpers = 0; break;
865 /* i386: int 0x80 = 0xcd 0x80 */
866 case 0x80cd: currpers = 1; break;
867 default:
868 currpers = current_personality;
869 fprintf(stderr,
870 "Unknown syscall opcode (0x%04X) while "
871 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200872 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200873 break;
874 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100875# endif
H.J. Lu35be5812012-04-16 13:00:01 +0200876# ifdef X32
H.J. Lu085e4282012-04-17 11:05:04 -0700877 /* Value of currpers:
878 * 0: 64 bit
879 * 1: 32 bit
880 * 2: X32
881 * Value of current_personality:
882 * 0: X32
883 * 1: 32 bit
884 */
885 switch (currpers) {
886 case 0:
887 fprintf(stderr, "syscall_%lu (...) in unsupported "
888 "64-bit mode of process PID=%d\n",
889 scno, tcp->pid);
890 return 0;
891 case 2:
892 currpers = 0;
H.J. Lu35be5812012-04-16 13:00:01 +0200893 }
H.J. Lu35be5812012-04-16 13:00:01 +0200894# endif
H.J. Lu085e4282012-04-17 11:05:04 -0700895 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100896#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000897# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200898 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000899 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200900 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200901 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200902 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000903 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200904 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000905 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200906 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100907#elif defined(ARM)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200908 /* Read complete register set in one go. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000909 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +0000910 return -1;
911
912 /*
913 * We only need to grab the syscall number on syscall entry.
914 */
915 if (regs.ARM_ip == 0) {
916 /*
917 * Note: we only deal with only 32-bit CPUs here.
918 */
919 if (regs.ARM_cpsr & 0x20) {
920 /*
921 * Get the Thumb-mode system call number
922 */
923 scno = regs.ARM_r7;
924 } else {
925 /*
926 * Get the ARM-mode system call number
927 */
928 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000929 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +0000930 if (errno)
931 return -1;
932
Roland McGrathf691bd22006-04-25 07:34:41 +0000933 /* Handle the EABI syscall convention. We do not
934 bother converting structures between the two
935 ABIs, but basic functionality should work even
936 if strace and the traced program have different
937 ABIs. */
938 if (scno == 0xef000000) {
939 scno = regs.ARM_r7;
940 } else {
941 if ((scno & 0x0ff00000) != 0x0f900000) {
942 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
943 scno);
944 return -1;
945 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000946
Roland McGrathf691bd22006-04-25 07:34:41 +0000947 /*
948 * Fixup the syscall number
949 */
950 scno &= 0x000fffff;
951 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000952 }
Roland McGrath56703312008-05-20 01:35:55 +0000953 if (scno & 0x0f0000) {
954 /*
955 * Handle ARM specific syscall
956 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000957 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +0000958 scno &= 0x0000ffff;
959 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000960 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +0000961
Roland McGrath0f87c492003-06-03 23:29:04 +0000962 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200963 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
964 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000965 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100966#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000967 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000968 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100969#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +0000970 unsigned long long regs[38];
971
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200972 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +0000973 return -1;
974 a3 = regs[REG_A3];
975 r2 = regs[REG_V0];
976
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200977 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200978 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200979 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100980 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200981 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000982 return 0;
983 }
Roland McGrath542c2c62008-05-20 01:11:56 +0000984 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100985#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000986 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000987 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200988 if (upeek(tcp, REG_V0, &scno) < 0)
989 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000990
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200991 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200992 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100993 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200994 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000995 return 0;
996 }
Wichert Akkermanf90da011999-10-31 21:15:38 +0000997 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100998#elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000999 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001000 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001001 if (upeek(tcp, REG_R0, &scno) < 0)
1002 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001003
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001004 /*
1005 * Do some sanity checks to figure out if it's
1006 * really a syscall entry
1007 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001008 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001009 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001010 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001011 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001012 return 0;
1013 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001014 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001015#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001016 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001017 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001018 return -1;
1019
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001020 /* Disassemble the syscall trap. */
1021 /* Retrieve the syscall trap instruction. */
1022 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001023# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001024 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1025 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001026# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001027 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001028# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001029 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001030 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001031
1032 /* Disassemble the trap to see what personality to use. */
1033 switch (trap) {
1034 case 0x91d02010:
1035 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001036 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001037 break;
1038 case 0x91d0206d:
1039 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001040 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001041 break;
1042 case 0x91d02000:
1043 /* SunOS syscall trap. (pers 1) */
1044 fprintf(stderr, "syscall: SunOS no support\n");
1045 return -1;
1046 case 0x91d02008:
1047 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001048 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001049 break;
1050 case 0x91d02009:
1051 /* NetBSD/FreeBSD syscall trap. */
1052 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1053 return -1;
1054 case 0x91d02027:
1055 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001056 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001057 break;
1058 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001059# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001060 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001061# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001062 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001063# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001064 return -1;
1065 }
1066
1067 /* Extract the system call number from the registers. */
1068 if (trap == 0x91d02027)
1069 scno = 156;
1070 else
1071 scno = regs.u_regs[U_REG_G1];
1072 if (scno == 0) {
1073 scno = regs.u_regs[U_REG_O0];
1074 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1075 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001076#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001077 if (upeek(tcp, PT_GR20, &scno) < 0)
1078 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001079#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001080 /*
1081 * In the new syscall ABI, the system call number is in R3.
1082 */
1083 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1084 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001085
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001086 if (scno < 0) {
1087 /* Odd as it may seem, a glibc bug has been known to cause
1088 glibc to issue bogus negative syscall numbers. So for
1089 our purposes, make strace print what it *should* have been */
1090 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001091 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001092 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001093 "Detected glibc bug: bogus system call"
1094 " number = %ld, correcting to %ld\n",
1095 scno,
1096 correct_scno);
1097 scno = correct_scno;
1098 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001099#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001100 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001101 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001102 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001103#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001104 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1105 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001106#elif defined(TILE)
Chris Metcalfc8c66982009-12-28 10:00:15 -05001107 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1108 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001109#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001110 if (upeek(tcp, 0, &scno) < 0)
1111 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001112#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001113
Denys Vlasenko523635f2012-02-25 02:44:25 +01001114#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001115 /* new syscall ABI returns result in R0 */
1116 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1117 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001118#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001119 /* ABI defines result returned in r9 */
1120 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1121 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001122#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001123
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001124 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001125 return 1;
1126}
1127
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001128/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001129 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001130 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1131 * 1: ok, continue in trace_syscall_entering().
1132 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001133 * ("????" etc) and bail out.
1134 */
Roland McGratha4d48532005-06-08 20:45:28 +00001135static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001136syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001137{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001138 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001139#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001140 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001141 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001142 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1143 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001144 }
H.J. Lu35be5812012-04-16 13:00:01 +02001145#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001146 {
1147 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001148 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001149 rax = (int)rax; /* sign extend from 32 bits */
1150 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001151 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001152 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1153 return 0;
1154 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001155 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001156#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001157 /* TODO: we already fetched PT_GPR2 in get_scno
1158 * and stored it in syscall_mode, reuse it here
1159 * instead of re-fetching?
1160 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001161 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001162 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001163 if (syscall_mode != -ENOSYS)
1164 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001165 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001166 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001167 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001168 return 0;
1169 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001170#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001171 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001172 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001173 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001174 if (d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001175 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001176 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001177 return 0;
1178 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001179#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001180 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001181 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001182 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001183 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001184 if (ia32 && r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001185 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001186 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001187 return 0;
1188 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001189#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001190 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001191 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001192 if (r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001193 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001194 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001195 return 0;
1196 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001197#elif defined(MICROBLAZE)
1198 if (upeek(tcp, 3 * 4, &r3) < 0)
1199 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001200 if (r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001201 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001202 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001203 return 0;
1204 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001205#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001206 return 1;
1207}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001208
Denys Vlasenko146b9442012-03-18 22:10:48 +01001209static void
1210internal_fork(struct tcb *tcp)
1211{
1212#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1213# define ARG_FLAGS 1
1214#else
1215# define ARG_FLAGS 0
1216#endif
1217#ifndef CLONE_UNTRACED
1218# define CLONE_UNTRACED 0x00800000
1219#endif
1220 if ((ptrace_setoptions
1221 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1222 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1223 return;
1224
1225 if (!followfork)
1226 return;
1227
1228 if (entering(tcp)) {
1229 /*
1230 * We won't see the new child if clone is called with
1231 * CLONE_UNTRACED, so we keep the same logic with that option
1232 * and don't trace it.
1233 */
1234 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1235 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1236 return;
1237 setbpt(tcp);
1238 } else {
1239 if (tcp->flags & TCB_BPTSET)
1240 clearbpt(tcp);
1241 }
1242}
1243
1244#if defined(TCB_WAITEXECVE)
1245static void
1246internal_exec(struct tcb *tcp)
1247{
1248 /* Maybe we have post-execve SIGTRAP suppressed? */
1249 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1250 return; /* yes, no need to do anything */
1251
1252 if (exiting(tcp) && syserror(tcp))
1253 /* Error in execve, no post-execve SIGTRAP expected */
1254 tcp->flags &= ~TCB_WAITEXECVE;
1255 else
1256 tcp->flags |= TCB_WAITEXECVE;
1257}
1258#endif
1259
1260static void
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001261internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001262{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001263 /*
1264 * We must always trace a few critical system calls in order to
1265 * correctly support following forks in the presence of tracing
1266 * qualifiers.
1267 */
1268 int (*func)();
1269
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001270 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001271 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001272
1273 func = sysent[tcp->scno].sys_func;
1274
1275 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001276 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001277 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001278 ) {
1279 internal_fork(tcp);
1280 return;
1281 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001282
Denys Vlasenko84703742012-02-25 02:38:52 +01001283#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001284 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001285# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001286 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001287# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001288 ) {
1289 internal_exec(tcp);
1290 return;
1291 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001292#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001293}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001294
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001295/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001296static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001297get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001298{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001299 int i, nargs;
1300
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001301 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001302 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001303 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001304 nargs = tcp->u_nargs = MAX_ARGS;
1305
Denys Vlasenko523635f2012-02-25 02:44:25 +01001306#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001307 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001308 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1309 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001310#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001311 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001312 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1313 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001314#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001315 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001316 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001317 long rbs_end;
1318 /* be backwards compatible with kernel < 2.4.4... */
1319# ifndef PT_RBS_END
1320# define PT_RBS_END PT_AR_BSP
1321# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001322
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001323 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1324 return -1;
1325 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001326 return -1;
1327
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001328 sof = (cfm >> 0) & 0x7f;
1329 sol = (cfm >> 7) & 0x7f;
1330 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1331
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001332 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001333 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1334 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1335 return -1;
1336 }
1337 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001338 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1339 PT_R9 /* ECX = out1 */,
1340 PT_R10 /* EDX = out2 */,
1341 PT_R14 /* ESI = out3 */,
1342 PT_R15 /* EDI = out4 */,
1343 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001344
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001345 for (i = 0; i < nargs; ++i) {
1346 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1347 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001348 /* truncate away IVE sign-extension */
1349 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001350 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001351 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001352#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001353 /* N32 and N64 both use up to six registers. */
1354 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001355
1356 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1357 return -1;
1358
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001359 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001360 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001361# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001362 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001363# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001364 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001365#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001366 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001367 long sp;
1368
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001369 if (upeek(tcp, REG_SP, &sp) < 0)
1370 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001371 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001372 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1373 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001374 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001375 (char *)(tcp->u_arg + 4));
1376 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001377 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001378 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001379 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001380 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001381#elif defined(POWERPC)
1382# ifndef PT_ORIG_R3
1383# define PT_ORIG_R3 34
1384# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001385 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001386 if (upeek(tcp, (i==0) ?
1387 (sizeof(unsigned long) * PT_ORIG_R3) :
1388 ((i+PT_R3) * sizeof(unsigned long)),
1389 &tcp->u_arg[i]) < 0)
1390 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001391 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001392#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001393 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001394 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001395#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001396 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001397 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1398 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001399#elif defined(ARM)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001400 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001401 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001402#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001403 (void)i;
1404 (void)nargs;
1405 tcp->u_arg[0] = regs.r12;
1406 tcp->u_arg[1] = regs.r11;
1407 tcp->u_arg[2] = regs.r10;
1408 tcp->u_arg[3] = regs.r9;
1409 tcp->u_arg[4] = regs.r5;
1410 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001411#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001412 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 +02001413
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001414 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001415 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1416 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001417#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001418 static const int syscall_regs[MAX_ARGS] = {
1419 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1420 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001421 };
1422
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001423 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001424 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001425 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001426#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001427 int i;
1428 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001429 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001430
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001431 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001432 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1433 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001434#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001435 (void)i;
1436 (void)nargs;
H.J. Lu35be5812012-04-16 13:00:01 +02001437 if (current_personality != 1) { /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001438 tcp->u_arg[0] = x86_64_regs.rdi;
1439 tcp->u_arg[1] = x86_64_regs.rsi;
1440 tcp->u_arg[2] = x86_64_regs.rdx;
1441 tcp->u_arg[3] = x86_64_regs.r10;
1442 tcp->u_arg[4] = x86_64_regs.r8;
1443 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001444# ifdef X32
1445 tcp->ext_arg[0] = x86_64_regs.rdi;
1446 tcp->ext_arg[1] = x86_64_regs.rsi;
1447 tcp->ext_arg[2] = x86_64_regs.rdx;
1448 tcp->ext_arg[3] = x86_64_regs.r10;
1449 tcp->ext_arg[4] = x86_64_regs.r8;
1450 tcp->ext_arg[5] = x86_64_regs.r9;
1451# endif
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001452 } else { /* i386 ABI */
1453 /* Sign-extend lower 32 bits */
1454 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1455 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1456 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1457 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1458 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1459 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1460 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001461#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001462 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001463 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1464 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001465#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001466 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001467 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001468 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001469 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001470
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001471 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001472 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1473 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001474#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001475 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001476 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1477 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001478#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001479 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001480 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1481 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001482#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001483 (void)i;
1484 (void)nargs;
1485 tcp->u_arg[0] = i386_regs.ebx;
1486 tcp->u_arg[1] = i386_regs.ecx;
1487 tcp->u_arg[2] = i386_regs.edx;
1488 tcp->u_arg[3] = i386_regs.esi;
1489 tcp->u_arg[4] = i386_regs.edi;
1490 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001491#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001492 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001493 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1494 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001495#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001496 return 1;
1497}
1498
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001499static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001500trace_syscall_entering(struct tcb *tcp)
1501{
1502 int res, scno_good;
1503
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001504#if defined TCB_WAITEXECVE
1505 if (tcp->flags & TCB_WAITEXECVE) {
1506 /* This is the post-execve SIGTRAP. */
1507 tcp->flags &= ~TCB_WAITEXECVE;
1508 return 0;
1509 }
1510#endif
1511
Denys Vlasenko06602d92011-08-24 17:53:52 +02001512 scno_good = res = get_scno(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001513 if (res == 0)
1514 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001515 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001516 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001517 if (res == 0)
1518 return res;
1519 if (res == 1)
1520 res = get_syscall_args(tcp);
1521 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001522
1523 if (res != 1) {
1524 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001525 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001526 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001527 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001528 tprintf("syscall_%lu(", tcp->scno);
1529 else
1530 tprintf("%s(", sysent[tcp->scno].sys_name);
1531 /*
1532 * " <unavailable>" will be added later by the code which
1533 * detects ptrace errors.
1534 */
1535 goto ret;
1536 }
1537
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001538#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1539 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001540# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001541 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001542 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001543 break;
1544 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001545# endif
1546# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001547 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001548 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001549 break;
1550 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001551# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001552 break;
1553 }
1554#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1555
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001556 internal_syscall(tcp);
1557
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001558 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001559 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1560 (tracing_paths && !pathtrace_match(tcp))) {
1561 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1562 return 0;
1563 }
1564
1565 tcp->flags &= ~TCB_FILTERED;
1566
1567 if (cflag == CFLAG_ONLY_STATS) {
1568 res = 0;
1569 goto ret;
1570 }
1571
1572 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001573 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001574 tprintf("syscall_%lu(", tcp->scno);
1575 else
1576 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001577 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001578 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1579 sysent[tcp->scno].sys_func != sys_exit))
1580 res = printargs(tcp);
1581 else
1582 res = (*sysent[tcp->scno].sys_func)(tcp);
1583
1584 if (fflush(tcp->outf) == EOF)
1585 return -1;
1586 ret:
1587 tcp->flags |= TCB_INSYSCALL;
1588 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001589 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001590 gettimeofday(&tcp->etime, NULL);
1591 return res;
1592}
1593
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001594/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001595 * 1: ok, continue in trace_syscall_exiting().
1596 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001597 * ("????" etc) and bail out.
1598 */
1599static int
1600get_syscall_result(struct tcb *tcp)
1601{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001602#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001603 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1604 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001605#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001606# define SO_MASK 0x10000000
1607 {
1608 long flags;
1609 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1610 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001611 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001612 return -1;
1613 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001614 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001615 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001616#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001617 /* Read complete register set in one go. */
1618 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1619 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001620#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001621 if (upeek(tcp, PT_R0, &r0) < 0)
1622 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001623#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001624 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001625 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001626#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001627 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001628 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001629#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001630# define IA64_PSR_IS ((long)1 << 34)
1631 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1632 ia32 = (psr & IA64_PSR_IS) != 0;
1633 if (upeek(tcp, PT_R8, &r8) < 0)
1634 return -1;
1635 if (upeek(tcp, PT_R10, &r10) < 0)
1636 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001637#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001638 /* Read complete register set in one go. */
1639 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1640 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001641#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001642 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1643 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001644#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001645 unsigned long long regs[38];
1646
1647 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1648 return -1;
1649 a3 = regs[REG_A3];
1650 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001651#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001652 if (upeek(tcp, REG_A3, &a3) < 0)
1653 return -1;
1654 if (upeek(tcp, REG_V0, &r2) < 0)
1655 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001656#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001657 if (upeek(tcp, REG_A3, &a3) < 0)
1658 return -1;
1659 if (upeek(tcp, REG_R0, &r0) < 0)
1660 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001661#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001662 /* Everything we need is in the current register set. */
1663 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1664 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001665#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001666 if (upeek(tcp, PT_GR28, &r28) < 0)
1667 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001668#elif defined(SH)
1669#elif defined(SH64)
1670#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001671 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1672 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001673#elif defined(TILE)
1674#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001675 if (upeek(tcp, 3 * 4, &r3) < 0)
1676 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001677#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001678
Denys Vlasenko523635f2012-02-25 02:44:25 +01001679#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001680 /* new syscall ABI returns result in R0 */
1681 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1682 return -1;
1683#elif defined(SH64)
1684 /* ABI defines result returned in r9 */
1685 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1686 return -1;
1687#endif
1688
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001689 return 1;
1690}
1691
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001692/* Called at each syscall exit */
1693static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001694syscall_fixup_on_sysexit(struct tcb *tcp)
1695{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001696#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001697 if (syscall_mode != -ENOSYS)
1698 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001699 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001700 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1701 /*
1702 * Return from execve.
1703 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1704 * flag set for the post-execve SIGTRAP to see and reset.
1705 */
1706 gpr2 = 0;
1707 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001708#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001709}
1710
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001711/*
1712 * Check the syscall return value register value for whether it is
1713 * a negated errno code indicating an error, or a success return value.
1714 */
1715static inline int
1716is_negated_errno(unsigned long int val)
1717{
1718 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001719#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001720 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001721 val = (unsigned int) val;
1722 max = (unsigned int) max;
1723 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001724#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001725 return val > max;
1726}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001727
Denys Vlasenko907735a2012-03-21 00:23:16 +01001728/* Returns:
1729 * 1: ok, continue in trace_syscall_exiting().
1730 * -1: error, trace_syscall_exiting() should print error indicator
1731 * ("????" etc) and bail out.
1732 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001733static int
1734get_error(struct tcb *tcp)
1735{
1736 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001737 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001738 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001739 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1740 check_errno = 0;
1741 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001742#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001743 if (check_errno && is_negated_errno(gpr2)) {
1744 tcp->u_rval = -1;
1745 u_error = -gpr2;
1746 }
1747 else {
1748 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001749 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001750#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001751 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001752 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001753 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001754 }
1755 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001756 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001757 }
H.J. Lu35be5812012-04-16 13:00:01 +02001758#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001759 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001760 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001761 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001762 }
1763 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001764 tcp->u_rval = x86_64_regs.rax;
H.J. Lu35be5812012-04-16 13:00:01 +02001765# if defined(X32)
1766 tcp->u_lrval = x86_64_regs.rax;
1767# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001768 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001769#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001770 if (ia32) {
1771 int err;
1772
1773 err = (int)r8;
1774 if (check_errno && is_negated_errno(err)) {
1775 tcp->u_rval = -1;
1776 u_error = -err;
1777 }
1778 else {
1779 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001780 }
1781 } else {
1782 if (check_errno && r10) {
1783 tcp->u_rval = -1;
1784 u_error = r8;
1785 } else {
1786 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001787 }
1788 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001789#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001790 if (check_errno && a3) {
1791 tcp->u_rval = -1;
1792 u_error = r2;
1793 } else {
1794 tcp->u_rval = r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02001795# if defined(LINUX_MIPSN32)
1796 tcp->u_lrval = r2;
1797# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001798 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001799#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001800 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001801 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001802 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001803 }
1804 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001805 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001806 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001807#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001808 if (check_errno && is_negated_errno(d0)) {
1809 tcp->u_rval = -1;
1810 u_error = -d0;
1811 }
1812 else {
1813 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001814 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001815#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001816 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1817 tcp->u_rval = -1;
1818 u_error = -regs.ARM_r0;
1819 }
1820 else {
1821 tcp->u_rval = regs.ARM_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001822 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001823#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001824 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1825 tcp->u_rval = -1;
1826 u_error = -regs.r12;
1827 }
1828 else {
1829 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001830 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001831#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001832 if (check_errno && is_negated_errno(r0)) {
1833 tcp->u_rval = -1;
1834 u_error = -r0;
1835 } else {
1836 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001837 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001838#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001839 if (check_errno && a3) {
1840 tcp->u_rval = -1;
1841 u_error = r0;
1842 }
1843 else {
1844 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001845 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001846#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001847 if (check_errno && regs.psr & PSR_C) {
1848 tcp->u_rval = -1;
1849 u_error = regs.u_regs[U_REG_O0];
1850 }
1851 else {
1852 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001853 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001854#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001855 if (check_errno && regs.tstate & 0x1100000000UL) {
1856 tcp->u_rval = -1;
1857 u_error = regs.u_regs[U_REG_O0];
1858 }
1859 else {
1860 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001861 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001862#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001863 if (check_errno && is_negated_errno(r28)) {
1864 tcp->u_rval = -1;
1865 u_error = -r28;
1866 }
1867 else {
1868 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001869 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001870#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001871 if (check_errno && is_negated_errno(r0)) {
1872 tcp->u_rval = -1;
1873 u_error = -r0;
1874 }
1875 else {
1876 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001877 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001878#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001879 if (check_errno && is_negated_errno(r9)) {
1880 tcp->u_rval = -1;
1881 u_error = -r9;
1882 }
1883 else {
1884 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001885 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001886#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001887 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1888 tcp->u_rval = -1;
1889 u_error = -r10;
1890 }
1891 else {
1892 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001893 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001894#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001895 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001896 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1897 return -1;
1898 if (check_errno && rval < 0 && rval > -nerrnos) {
1899 tcp->u_rval = -1;
1900 u_error = -rval;
1901 }
1902 else {
1903 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001904 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001905#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001906 if (check_errno && is_negated_errno(r3)) {
1907 tcp->u_rval = -1;
1908 u_error = -r3;
1909 }
1910 else {
1911 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001912 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001913#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001914 tcp->u_error = u_error;
1915 return 1;
1916}
1917
1918static void
1919dumpio(struct tcb *tcp)
1920{
1921 if (syserror(tcp))
1922 return;
1923 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1924 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001925 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001926 return;
1927 if (sysent[tcp->scno].sys_func == printargs)
1928 return;
1929 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1930 if (sysent[tcp->scno].sys_func == sys_read ||
1931 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001932 sysent[tcp->scno].sys_func == sys_recv ||
1933 sysent[tcp->scno].sys_func == sys_recvfrom)
1934 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1935 else if (sysent[tcp->scno].sys_func == sys_readv)
1936 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1937 return;
1938 }
1939 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1940 if (sysent[tcp->scno].sys_func == sys_write ||
1941 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001942 sysent[tcp->scno].sys_func == sys_send ||
1943 sysent[tcp->scno].sys_func == sys_sendto)
1944 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1945 else if (sysent[tcp->scno].sys_func == sys_writev)
1946 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1947 return;
1948 }
1949}
1950
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001951static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001952trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001953{
1954 int sys_res;
1955 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001956 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001957 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001958
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001959 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001960 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001961 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001962
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001963#if SUPPORTED_PERSONALITIES > 1
1964 update_personality(tcp, tcp->currpers);
1965#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001966 res = get_syscall_result(tcp);
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001967 if (res == 1) {
1968 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01001969 res = get_error(tcp); /* returns 1 or -1 */
1970 if (res == 1) {
1971 internal_syscall(tcp);
1972 if (filtered(tcp)) {
1973 goto ret;
1974 }
1975 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00001976 }
1977
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001978 if (cflag) {
1979 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02001980 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02001981 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001982 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001983 }
1984 }
1985
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01001986 /* If not in -ff mode, and printing_tcp != tcp,
1987 * then the log currently does not end with output
1988 * of _our syscall entry_, but with something else.
1989 * We need to say which syscall's return is this.
1990 *
1991 * Forced reprinting via TCB_REPRINT is used only by
1992 * "strace -ff -oLOG test/threaded_execve" corner case.
1993 * It's the only case when -ff mode needs reprinting.
1994 */
1995 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
1996 tcp->flags &= ~TCB_REPRINT;
1997 printleader(tcp);
1998 if (!SCNO_IN_RANGE(tcp->scno))
1999 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2000 else
2001 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2002 }
2003 printing_tcp = tcp;
2004
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002005 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002006 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002007 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002008 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002009 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002010 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002011 tcp->flags &= ~TCB_INSYSCALL;
2012 return res;
2013 }
2014
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002015 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002016 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002017 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002018 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002019 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002020 /* FIXME: not_failing_only (IOW, option -z) is broken:
2021 * failure of syscall is known only after syscall return.
2022 * Thus we end up with something like this on, say, ENOENT:
2023 * open("doesnt_exist", O_RDONLY <unfinished ...>
2024 * {next syscall decode}
2025 * whereas the intended result is that open(...) line
2026 * is not shown at all.
2027 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002028 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002029 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002030 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2031 }
2032
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002033 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002034 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002035 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002036 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002037 qual_flags[tcp->scno] & QUAL_RAW) {
2038 if (u_error)
2039 tprintf("= -1 (errno %ld)", u_error);
2040 else
2041 tprintf("= %#lx", tcp->u_rval);
2042 }
2043 else if (!(sys_res & RVAL_NONE) && u_error) {
2044 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002045 /* Blocked signals do not interrupt any syscalls.
2046 * In this case syscalls don't return ERESTARTfoo codes.
2047 *
2048 * Deadly signals set to SIG_DFL interrupt syscalls
2049 * and kill the process regardless of which of the codes below
2050 * is returned by the interrupted syscall.
2051 * In some cases, kernel forces a kernel-generated deadly
2052 * signal to be unblocked and set to SIG_DFL (and thus cause
2053 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2054 * or SIGILL. (The alternative is to leave process spinning
2055 * forever on the faulty instruction - not useful).
2056 *
2057 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2058 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2059 * but kernel will always restart them.
2060 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002061 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002062 /* Most common type of signal-interrupted syscall exit code.
2063 * The system call will be restarted with the same arguments
2064 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2065 */
2066 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002067 break;
2068 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002069 /* Rare. For example, fork() returns this if interrupted.
2070 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2071 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002072 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002073 break;
2074 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002075 /* pause(), rt_sigsuspend() etc use this code.
2076 * SA_RESTART is ignored (assumed not set):
2077 * syscall won't restart (will return EINTR instead)
2078 * even after signal with SA_RESTART set.
2079 * However, after SIG_IGN or SIG_DFL signal it will.
2080 */
2081 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002082 break;
2083 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002084 /* Syscalls like nanosleep(), poll() which can't be
2085 * restarted with their original arguments use this
2086 * code. Kernel will execute restart_syscall() instead,
2087 * which changes arguments before restarting syscall.
2088 * SA_RESTART is ignored (assumed not set) similarly
2089 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2090 * since restart data is saved in "restart block"
2091 * in task struct, and if signal handler uses a syscall
2092 * which in turn saves another such restart block,
2093 * old data is lost and restart becomes impossible)
2094 */
2095 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002096 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002097 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002098 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002099 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002100 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002101 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002102 strerror(u_error));
2103 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002104 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002105 strerror(u_error));
2106 break;
2107 }
2108 if ((sys_res & RVAL_STR) && tcp->auxstr)
2109 tprintf(" (%s)", tcp->auxstr);
2110 }
2111 else {
2112 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002113 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002114 else {
2115 switch (sys_res & RVAL_MASK) {
2116 case RVAL_HEX:
2117 tprintf("= %#lx", tcp->u_rval);
2118 break;
2119 case RVAL_OCTAL:
2120 tprintf("= %#lo", tcp->u_rval);
2121 break;
2122 case RVAL_UDECIMAL:
2123 tprintf("= %lu", tcp->u_rval);
2124 break;
2125 case RVAL_DECIMAL:
2126 tprintf("= %ld", tcp->u_rval);
2127 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002128#if defined(LINUX_MIPSN32) || defined(X32)
2129 /*
2130 case RVAL_LHEX:
2131 tprintf("= %#llx", tcp->u_lrval);
2132 break;
2133 case RVAL_LOCTAL:
2134 tprintf("= %#llo", tcp->u_lrval);
2135 break;
2136 */
2137 case RVAL_LUDECIMAL:
2138 tprintf("= %llu", tcp->u_lrval);
2139 break;
2140 /*
2141 case RVAL_LDECIMAL:
2142 tprintf("= %lld", tcp->u_lrval);
2143 break;
2144 */
2145#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002146 default:
2147 fprintf(stderr,
2148 "invalid rval format\n");
2149 break;
2150 }
2151 }
2152 if ((sys_res & RVAL_STR) && tcp->auxstr)
2153 tprintf(" (%s)", tcp->auxstr);
2154 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002155 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002156 tv_sub(&tv, &tv, &tcp->etime);
2157 tprintf(" <%ld.%06ld>",
2158 (long) tv.tv_sec, (long) tv.tv_usec);
2159 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002160 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002161 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002162 line_ended();
2163
Denys Vlasenko3b738812011-08-22 02:06:35 +02002164 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002165 tcp->flags &= ~TCB_INSYSCALL;
2166 return 0;
2167}
2168
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002169int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002170trace_syscall(struct tcb *tcp)
2171{
2172 return exiting(tcp) ?
2173 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2174}