blob: c4c5e86830616d44beb63748a65f562878faccb7 [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) {
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000724 perror_msg("%s", "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
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001584 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001585 ret:
1586 tcp->flags |= TCB_INSYSCALL;
1587 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001588 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001589 gettimeofday(&tcp->etime, NULL);
1590 return res;
1591}
1592
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001593/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001594 * 1: ok, continue in trace_syscall_exiting().
1595 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001596 * ("????" etc) and bail out.
1597 */
1598static int
1599get_syscall_result(struct tcb *tcp)
1600{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001601#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001602 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1603 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001604#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001605# define SO_MASK 0x10000000
1606 {
1607 long flags;
1608 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1609 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001610 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001611 return -1;
1612 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001613 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001614 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001615#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001616 /* Read complete register set in one go. */
1617 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1618 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001619#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001620 if (upeek(tcp, PT_R0, &r0) < 0)
1621 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001622#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001623 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001624 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001625#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001626 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001627 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001628#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001629# define IA64_PSR_IS ((long)1 << 34)
1630 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1631 ia32 = (psr & IA64_PSR_IS) != 0;
1632 if (upeek(tcp, PT_R8, &r8) < 0)
1633 return -1;
1634 if (upeek(tcp, PT_R10, &r10) < 0)
1635 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001636#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001637 /* Read complete register set in one go. */
1638 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1639 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001640#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001641 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1642 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001643#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001644 unsigned long long regs[38];
1645
1646 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1647 return -1;
1648 a3 = regs[REG_A3];
1649 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001650#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001651 if (upeek(tcp, REG_A3, &a3) < 0)
1652 return -1;
1653 if (upeek(tcp, REG_V0, &r2) < 0)
1654 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001655#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001656 if (upeek(tcp, REG_A3, &a3) < 0)
1657 return -1;
1658 if (upeek(tcp, REG_R0, &r0) < 0)
1659 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001660#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001661 /* Everything we need is in the current register set. */
1662 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1663 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001664#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001665 if (upeek(tcp, PT_GR28, &r28) < 0)
1666 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001667#elif defined(SH)
1668#elif defined(SH64)
1669#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001670 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1671 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001672#elif defined(TILE)
1673#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001674 if (upeek(tcp, 3 * 4, &r3) < 0)
1675 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001676#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001677
Denys Vlasenko523635f2012-02-25 02:44:25 +01001678#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001679 /* new syscall ABI returns result in R0 */
1680 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1681 return -1;
1682#elif defined(SH64)
1683 /* ABI defines result returned in r9 */
1684 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1685 return -1;
1686#endif
1687
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001688 return 1;
1689}
1690
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001691/* Called at each syscall exit */
1692static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001693syscall_fixup_on_sysexit(struct tcb *tcp)
1694{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001695#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001696 if (syscall_mode != -ENOSYS)
1697 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001698 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001699 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1700 /*
1701 * Return from execve.
1702 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1703 * flag set for the post-execve SIGTRAP to see and reset.
1704 */
1705 gpr2 = 0;
1706 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001707#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001708}
1709
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001710/*
1711 * Check the syscall return value register value for whether it is
1712 * a negated errno code indicating an error, or a success return value.
1713 */
1714static inline int
1715is_negated_errno(unsigned long int val)
1716{
1717 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001718#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001719 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001720 val = (unsigned int) val;
1721 max = (unsigned int) max;
1722 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001723#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001724 return val > max;
1725}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001726
Denys Vlasenko907735a2012-03-21 00:23:16 +01001727/* Returns:
1728 * 1: ok, continue in trace_syscall_exiting().
1729 * -1: error, trace_syscall_exiting() should print error indicator
1730 * ("????" etc) and bail out.
1731 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001732static int
1733get_error(struct tcb *tcp)
1734{
1735 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001736 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001737 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001738 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1739 check_errno = 0;
1740 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001741#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001742 if (check_errno && is_negated_errno(gpr2)) {
1743 tcp->u_rval = -1;
1744 u_error = -gpr2;
1745 }
1746 else {
1747 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001748 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001749#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001750 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001751 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001752 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001753 }
1754 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001755 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001756 }
H.J. Lu35be5812012-04-16 13:00:01 +02001757#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001758 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001759 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001760 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001761 }
1762 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001763 tcp->u_rval = x86_64_regs.rax;
H.J. Lu35be5812012-04-16 13:00:01 +02001764# if defined(X32)
1765 tcp->u_lrval = x86_64_regs.rax;
1766# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001767 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001768#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001769 if (ia32) {
1770 int err;
1771
1772 err = (int)r8;
1773 if (check_errno && is_negated_errno(err)) {
1774 tcp->u_rval = -1;
1775 u_error = -err;
1776 }
1777 else {
1778 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001779 }
1780 } else {
1781 if (check_errno && r10) {
1782 tcp->u_rval = -1;
1783 u_error = r8;
1784 } else {
1785 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001786 }
1787 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001788#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001789 if (check_errno && a3) {
1790 tcp->u_rval = -1;
1791 u_error = r2;
1792 } else {
1793 tcp->u_rval = r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02001794# if defined(LINUX_MIPSN32)
1795 tcp->u_lrval = r2;
1796# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001797 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001798#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001799 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001800 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001801 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001802 }
1803 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001804 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001805 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001806#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001807 if (check_errno && is_negated_errno(d0)) {
1808 tcp->u_rval = -1;
1809 u_error = -d0;
1810 }
1811 else {
1812 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001813 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001814#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001815 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1816 tcp->u_rval = -1;
1817 u_error = -regs.ARM_r0;
1818 }
1819 else {
1820 tcp->u_rval = regs.ARM_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001821 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001822#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001823 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1824 tcp->u_rval = -1;
1825 u_error = -regs.r12;
1826 }
1827 else {
1828 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001829 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001830#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001831 if (check_errno && is_negated_errno(r0)) {
1832 tcp->u_rval = -1;
1833 u_error = -r0;
1834 } else {
1835 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001836 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001837#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001838 if (check_errno && a3) {
1839 tcp->u_rval = -1;
1840 u_error = r0;
1841 }
1842 else {
1843 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001844 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001845#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001846 if (check_errno && regs.psr & PSR_C) {
1847 tcp->u_rval = -1;
1848 u_error = regs.u_regs[U_REG_O0];
1849 }
1850 else {
1851 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001852 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001853#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001854 if (check_errno && regs.tstate & 0x1100000000UL) {
1855 tcp->u_rval = -1;
1856 u_error = regs.u_regs[U_REG_O0];
1857 }
1858 else {
1859 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001860 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001861#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001862 if (check_errno && is_negated_errno(r28)) {
1863 tcp->u_rval = -1;
1864 u_error = -r28;
1865 }
1866 else {
1867 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001868 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001869#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001870 if (check_errno && is_negated_errno(r0)) {
1871 tcp->u_rval = -1;
1872 u_error = -r0;
1873 }
1874 else {
1875 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001876 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001877#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001878 if (check_errno && is_negated_errno(r9)) {
1879 tcp->u_rval = -1;
1880 u_error = -r9;
1881 }
1882 else {
1883 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001884 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001885#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001886 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1887 tcp->u_rval = -1;
1888 u_error = -r10;
1889 }
1890 else {
1891 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001892 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001893#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001894 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001895 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1896 return -1;
1897 if (check_errno && rval < 0 && rval > -nerrnos) {
1898 tcp->u_rval = -1;
1899 u_error = -rval;
1900 }
1901 else {
1902 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001903 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001904#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001905 if (check_errno && is_negated_errno(r3)) {
1906 tcp->u_rval = -1;
1907 u_error = -r3;
1908 }
1909 else {
1910 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001911 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001912#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001913 tcp->u_error = u_error;
1914 return 1;
1915}
1916
1917static void
1918dumpio(struct tcb *tcp)
1919{
1920 if (syserror(tcp))
1921 return;
1922 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1923 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001924 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001925 return;
1926 if (sysent[tcp->scno].sys_func == printargs)
1927 return;
1928 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1929 if (sysent[tcp->scno].sys_func == sys_read ||
1930 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001931 sysent[tcp->scno].sys_func == sys_recv ||
1932 sysent[tcp->scno].sys_func == sys_recvfrom)
1933 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1934 else if (sysent[tcp->scno].sys_func == sys_readv)
1935 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1936 return;
1937 }
1938 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1939 if (sysent[tcp->scno].sys_func == sys_write ||
1940 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001941 sysent[tcp->scno].sys_func == sys_send ||
1942 sysent[tcp->scno].sys_func == sys_sendto)
1943 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1944 else if (sysent[tcp->scno].sys_func == sys_writev)
1945 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1946 return;
1947 }
1948}
1949
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001950static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001951trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001952{
1953 int sys_res;
1954 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001955 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001956 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001957
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001958 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001959 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001960 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001961
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001962#if SUPPORTED_PERSONALITIES > 1
1963 update_personality(tcp, tcp->currpers);
1964#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001965 res = get_syscall_result(tcp);
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001966 if (res == 1) {
1967 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01001968 res = get_error(tcp); /* returns 1 or -1 */
1969 if (res == 1) {
1970 internal_syscall(tcp);
1971 if (filtered(tcp)) {
1972 goto ret;
1973 }
1974 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00001975 }
1976
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001977 if (cflag) {
1978 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02001979 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02001980 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001981 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001982 }
1983 }
1984
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01001985 /* If not in -ff mode, and printing_tcp != tcp,
1986 * then the log currently does not end with output
1987 * of _our syscall entry_, but with something else.
1988 * We need to say which syscall's return is this.
1989 *
1990 * Forced reprinting via TCB_REPRINT is used only by
1991 * "strace -ff -oLOG test/threaded_execve" corner case.
1992 * It's the only case when -ff mode needs reprinting.
1993 */
1994 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
1995 tcp->flags &= ~TCB_REPRINT;
1996 printleader(tcp);
1997 if (!SCNO_IN_RANGE(tcp->scno))
1998 tprintf("<... syscall_%lu resumed> ", tcp->scno);
1999 else
2000 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2001 }
2002 printing_tcp = tcp;
2003
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002004 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002005 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002006 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002007 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002008 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002009 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002010 tcp->flags &= ~TCB_INSYSCALL;
2011 return res;
2012 }
2013
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002014 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002015 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002016 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002017 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002018 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002019 /* FIXME: not_failing_only (IOW, option -z) is broken:
2020 * failure of syscall is known only after syscall return.
2021 * Thus we end up with something like this on, say, ENOENT:
2022 * open("doesnt_exist", O_RDONLY <unfinished ...>
2023 * {next syscall decode}
2024 * whereas the intended result is that open(...) line
2025 * is not shown at all.
2026 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002027 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002028 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002029 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2030 }
2031
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002032 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002033 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002034 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002035 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002036 qual_flags[tcp->scno] & QUAL_RAW) {
2037 if (u_error)
2038 tprintf("= -1 (errno %ld)", u_error);
2039 else
2040 tprintf("= %#lx", tcp->u_rval);
2041 }
2042 else if (!(sys_res & RVAL_NONE) && u_error) {
2043 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002044 /* Blocked signals do not interrupt any syscalls.
2045 * In this case syscalls don't return ERESTARTfoo codes.
2046 *
2047 * Deadly signals set to SIG_DFL interrupt syscalls
2048 * and kill the process regardless of which of the codes below
2049 * is returned by the interrupted syscall.
2050 * In some cases, kernel forces a kernel-generated deadly
2051 * signal to be unblocked and set to SIG_DFL (and thus cause
2052 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2053 * or SIGILL. (The alternative is to leave process spinning
2054 * forever on the faulty instruction - not useful).
2055 *
2056 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2057 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2058 * but kernel will always restart them.
2059 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002060 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002061 /* Most common type of signal-interrupted syscall exit code.
2062 * The system call will be restarted with the same arguments
2063 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2064 */
2065 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002066 break;
2067 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002068 /* Rare. For example, fork() returns this if interrupted.
2069 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2070 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002071 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002072 break;
2073 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002074 /* pause(), rt_sigsuspend() etc use this code.
2075 * SA_RESTART is ignored (assumed not set):
2076 * syscall won't restart (will return EINTR instead)
2077 * even after signal with SA_RESTART set.
2078 * However, after SIG_IGN or SIG_DFL signal it will.
2079 */
2080 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002081 break;
2082 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002083 /* Syscalls like nanosleep(), poll() which can't be
2084 * restarted with their original arguments use this
2085 * code. Kernel will execute restart_syscall() instead,
2086 * which changes arguments before restarting syscall.
2087 * SA_RESTART is ignored (assumed not set) similarly
2088 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2089 * since restart data is saved in "restart block"
2090 * in task struct, and if signal handler uses a syscall
2091 * which in turn saves another such restart block,
2092 * old data is lost and restart becomes impossible)
2093 */
2094 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002095 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002096 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002097 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002098 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002099 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002100 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002101 strerror(u_error));
2102 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002103 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002104 strerror(u_error));
2105 break;
2106 }
2107 if ((sys_res & RVAL_STR) && tcp->auxstr)
2108 tprintf(" (%s)", tcp->auxstr);
2109 }
2110 else {
2111 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002112 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002113 else {
2114 switch (sys_res & RVAL_MASK) {
2115 case RVAL_HEX:
2116 tprintf("= %#lx", tcp->u_rval);
2117 break;
2118 case RVAL_OCTAL:
2119 tprintf("= %#lo", tcp->u_rval);
2120 break;
2121 case RVAL_UDECIMAL:
2122 tprintf("= %lu", tcp->u_rval);
2123 break;
2124 case RVAL_DECIMAL:
2125 tprintf("= %ld", tcp->u_rval);
2126 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002127#if defined(LINUX_MIPSN32) || defined(X32)
2128 /*
2129 case RVAL_LHEX:
2130 tprintf("= %#llx", tcp->u_lrval);
2131 break;
2132 case RVAL_LOCTAL:
2133 tprintf("= %#llo", tcp->u_lrval);
2134 break;
2135 */
2136 case RVAL_LUDECIMAL:
2137 tprintf("= %llu", tcp->u_lrval);
2138 break;
2139 /*
2140 case RVAL_LDECIMAL:
2141 tprintf("= %lld", tcp->u_lrval);
2142 break;
2143 */
2144#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002145 default:
2146 fprintf(stderr,
2147 "invalid rval format\n");
2148 break;
2149 }
2150 }
2151 if ((sys_res & RVAL_STR) && tcp->auxstr)
2152 tprintf(" (%s)", tcp->auxstr);
2153 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002154 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002155 tv_sub(&tv, &tv, &tcp->etime);
2156 tprintf(" <%ld.%06ld>",
2157 (long) tv.tv_sec, (long) tv.tv_usec);
2158 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002159 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002160 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002161 line_ended();
2162
Denys Vlasenko3b738812011-08-22 02:06:35 +02002163 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002164 tcp->flags &= ~TCB_INSYSCALL;
2165 return 0;
2166}
2167
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002168int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002169trace_syscall(struct tcb *tcp)
2170{
2171 return exiting(tcp) ?
2172 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2173}