blob: 37936ad48d3cfd5fea47ff987f4a79bf31a42c74 [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
Namhyung Kim96792962012-10-24 11:41:57 +0900100#define TM TRACE_MEMORY
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000101#define NF SYSCALL_NEVER_FAILS
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200102#define MA MAX_ARGS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000103
Roland McGrathee36ce12004-09-04 03:53:10 +0000104static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000105#include "syscallent.h"
106};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000107
108#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000109static const struct sysent sysent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100110# include "syscallent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000111};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200112#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000113
114#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000115static const struct sysent sysent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100116# include "syscallent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000117};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200118#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000119
120/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000121#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122#undef TF
123#undef TI
124#undef TN
125#undef TP
126#undef TS
Namhyung Kim96792962012-10-24 11:41:57 +0900127#undef TM
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000128#undef NF
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200129#undef MA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130
Denys Vlasenko39fca622011-08-20 02:12:33 +0200131/*
132 * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
133 * program `ioctlsort', such that the list is sorted by the `code' field.
134 * This has the side-effect of resolving the _IO.. macros into
135 * plain integers, eliminating the need to include here everything
136 * in "/usr/include".
137 */
138
Roland McGrathee36ce12004-09-04 03:53:10 +0000139static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000140#include "errnoent.h"
141};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200142static const char *const signalent0[] = {
143#include "signalent.h"
144};
145static const struct ioctlent ioctlent0[] = {
146#include "ioctlent.h"
147};
148enum { nsyscalls0 = ARRAY_SIZE(sysent0) };
149enum { nerrnos0 = ARRAY_SIZE(errnoent0) };
150enum { nsignals0 = ARRAY_SIZE(signalent0) };
151enum { nioctlents0 = ARRAY_SIZE(ioctlent0) };
152int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000153
154#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000155static const char *const errnoent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100156# include "errnoent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000157};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200158static const char *const signalent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100159# include "signalent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200160};
161static const struct ioctlent ioctlent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100162# include "ioctlent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200163};
164enum { nsyscalls1 = ARRAY_SIZE(sysent1) };
165enum { nerrnos1 = ARRAY_SIZE(errnoent1) };
166enum { nsignals1 = ARRAY_SIZE(signalent1) };
167enum { nioctlents1 = ARRAY_SIZE(ioctlent1) };
168int qual_flags1[MAX_QUALS];
169#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000170
171#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000172static const char *const errnoent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100173# include "errnoent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000174};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200175static const char *const signalent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100176# include "signalent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200177};
178static const struct ioctlent ioctlent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100179# include "ioctlent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200180};
181enum { nsyscalls2 = ARRAY_SIZE(sysent2) };
182enum { nerrnos2 = ARRAY_SIZE(errnoent2) };
183enum { nsignals2 = ARRAY_SIZE(signalent2) };
184enum { nioctlents2 = ARRAY_SIZE(ioctlent2) };
185int qual_flags2[MAX_QUALS];
186#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000187
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100188const struct sysent *sysent = sysent0;
189const char *const *errnoent = errnoent0;
190const char *const *signalent = signalent0;
191const struct ioctlent *ioctlent = ioctlent0;
192unsigned nsyscalls = nsyscalls0;
193unsigned nerrnos = nerrnos0;
194unsigned nsignals = nsignals0;
195unsigned nioctlents = nioctlents0;
196int *qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000197
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100198#if SUPPORTED_PERSONALITIES > 1
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000199int current_personality;
200
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000201const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
202 PERSONALITY0_WORDSIZE,
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000203 PERSONALITY1_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100204# if SUPPORTED_PERSONALITIES > 2
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000205 PERSONALITY2_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100206# endif
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200207};
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000208
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200209void
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000210set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000211{
212 switch (personality) {
213 case 0:
214 errnoent = errnoent0;
215 nerrnos = nerrnos0;
216 sysent = sysent0;
217 nsyscalls = nsyscalls0;
218 ioctlent = ioctlent0;
219 nioctlents = nioctlents0;
220 signalent = signalent0;
221 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000222 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000223 break;
224
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000225 case 1:
226 errnoent = errnoent1;
227 nerrnos = nerrnos1;
228 sysent = sysent1;
229 nsyscalls = nsyscalls1;
230 ioctlent = ioctlent1;
231 nioctlents = nioctlents1;
232 signalent = signalent1;
233 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000234 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000235 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000236
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100237# if SUPPORTED_PERSONALITIES >= 3
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000238 case 2:
239 errnoent = errnoent2;
240 nerrnos = nerrnos2;
241 sysent = sysent2;
242 nsyscalls = nsyscalls2;
243 ioctlent = ioctlent2;
244 nioctlents = nioctlents2;
245 signalent = signalent2;
246 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000247 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000248 break;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100249# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000250 }
251
252 current_personality = personality;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000253}
254
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000255static void
256update_personality(struct tcb *tcp, int personality)
257{
258 if (personality == current_personality)
259 return;
260 set_personality(personality);
261
262 if (personality == tcp->currpers)
263 return;
264 tcp->currpers = personality;
265
H.J. Lu35be5812012-04-16 13:00:01 +0200266# if defined(POWERPC64)
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000267 if (!qflag) {
268 static const char *const names[] = {"64 bit", "32 bit"};
269 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
270 tcp->pid, names[personality]);
271 }
H.J. Lu35be5812012-04-16 13:00:01 +0200272# elif defined(X86_64)
273 if (!qflag) {
274 static const char *const names[] = {"64 bit", "32 bit", "x32"};
275 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
276 tcp->pid, names[personality]);
277 }
H.J. Lu085e4282012-04-17 11:05:04 -0700278# elif defined(X32)
279 if (!qflag) {
280 static const char *const names[] = {"x32", "32 bit"};
281 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
282 tcp->pid, names[personality]);
283 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100284# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000285}
286#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000287
Roland McGrath9797ceb2002-12-30 10:23:00 +0000288static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000289
Roland McGrathe10e62a2004-09-04 04:20:43 +0000290static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000291 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000292 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000293 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000294 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000295} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000296 { QUAL_TRACE, "trace", qual_syscall, "system call" },
297 { QUAL_TRACE, "t", qual_syscall, "system call" },
298 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
299 { QUAL_ABBREV, "a", qual_syscall, "system call" },
300 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
301 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
302 { QUAL_RAW, "raw", qual_syscall, "system call" },
303 { QUAL_RAW, "x", qual_syscall, "system call" },
304 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
305 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
306 { QUAL_SIGNAL, "s", qual_signal, "signal" },
307 { QUAL_FAULT, "fault", qual_fault, "fault" },
308 { QUAL_FAULT, "faults", qual_fault, "fault" },
309 { QUAL_FAULT, "m", qual_fault, "fault" },
310 { QUAL_READ, "read", qual_desc, "descriptor" },
311 { QUAL_READ, "reads", qual_desc, "descriptor" },
312 { QUAL_READ, "r", qual_desc, "descriptor" },
313 { QUAL_WRITE, "write", qual_desc, "descriptor" },
314 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
315 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000316 { 0, NULL, NULL, NULL },
317};
318
Roland McGrath9797ceb2002-12-30 10:23:00 +0000319static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000320qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000321{
Roland McGrath138c6a32006-01-12 09:50:49 +0000322 if (pers == 0 || pers < 0) {
323 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000324 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000325 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000326 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000327 }
328
329#if SUPPORTED_PERSONALITIES >= 2
330 if (pers == 1 || pers < 0) {
331 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000332 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000333 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000334 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000335 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100336#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000337
338#if SUPPORTED_PERSONALITIES >= 3
339 if (pers == 2 || pers < 0) {
340 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000341 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000342 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000343 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000344 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100345#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000346}
347
348static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000349qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000350{
351 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000352 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000353
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100354 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000355 int i = string_to_uint(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000356 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000357 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000358 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000359 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000360 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000361 for (i = 0; i < nsyscalls0; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000362 if (sysent0[i].sys_name &&
363 strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000364 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000365 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000366 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000367
368#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000369 for (i = 0; i < nsyscalls1; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000370 if (sysent1[i].sys_name &&
371 strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000372 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000373 rc = 0;
374 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100375#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000376
377#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000378 for (i = 0; i < nsyscalls2; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000379 if (sysent2[i].sys_name &&
380 strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000381 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000382 rc = 0;
383 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100384#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000385
Roland McGrathfe6b3522005-02-02 04:40:11 +0000386 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000387}
388
389static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000390qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000391{
392 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000393
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100394 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000395 int signo = string_to_uint(s);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000396 if (signo < 0 || signo >= MAX_QUALS)
397 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000398 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000399 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000400 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000401 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000402 s += 3;
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100403 for (i = 0; i <= NSIG; i++) {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000404 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000405 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000406 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000407 }
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100408 }
Roland McGrath76421df2005-02-02 03:51:18 +0000409 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000410}
411
412static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000413qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000414{
415 return -1;
416}
417
418static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000419qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000420{
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100421 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000422 int desc = string_to_uint(s);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000423 if (desc < 0 || desc >= MAX_QUALS)
424 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000425 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000426 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000427 }
428 return -1;
429}
430
431static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000432lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000433{
434 if (strcmp(s, "file") == 0)
435 return TRACE_FILE;
436 if (strcmp(s, "ipc") == 0)
437 return TRACE_IPC;
438 if (strcmp(s, "network") == 0)
439 return TRACE_NETWORK;
440 if (strcmp(s, "process") == 0)
441 return TRACE_PROCESS;
442 if (strcmp(s, "signal") == 0)
443 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000444 if (strcmp(s, "desc") == 0)
445 return TRACE_DESC;
Namhyung Kim96792962012-10-24 11:41:57 +0900446 if (strcmp(s, "memory") == 0)
447 return TRACE_MEMORY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000448 return -1;
449}
450
451void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000452qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000453{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000454 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000455 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000456 char *copy;
457 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000458 int i, n;
459
460 opt = &qual_options[0];
461 for (i = 0; (p = qual_options[i].option_name); i++) {
462 n = strlen(p);
463 if (strncmp(s, p, n) == 0 && s[n] == '=') {
464 opt = &qual_options[i];
465 s += n + 1;
466 break;
467 }
468 }
469 not = 0;
470 if (*s == '!') {
471 not = 1;
472 s++;
473 }
474 if (strcmp(s, "none") == 0) {
475 not = 1 - not;
476 s = "all";
477 }
478 if (strcmp(s, "all") == 0) {
479 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000480 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000481 }
482 return;
483 }
484 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000485 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000486 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200487 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200488 if (!copy)
489 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000490 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000491 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000492 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000493 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000494 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000495
496#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000497 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000498 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000499 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100500#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000501
502#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000503 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000504 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000505 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100506#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000507
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000508 continue;
509 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000510 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100511 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000512 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000513 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000514 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000515 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000516 return;
517}
518
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000519#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000520static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000521decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000522{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000523 unsigned long addr;
524 unsigned int i, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000525
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000526 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
527 return;
528
529 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
530 addr = tcp->u_arg[1];
531 tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100532 size = current_wordsize;
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000533 for (i = 0; i < tcp->u_nargs; ++i) {
534 if (size == sizeof(int)) {
535 unsigned int arg;
536 if (umove(tcp, addr, &arg) < 0)
537 arg = 0;
538 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000539 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000540 else {
541 unsigned long arg;
542 if (umove(tcp, addr, &arg) < 0)
543 arg = 0;
544 tcp->u_arg[i] = arg;
545 }
546 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000547 }
548}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000549#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400550
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000551#ifdef SYS_ipc_subcall
552static void
553decode_ipc_subcall(struct tcb *tcp)
554{
555 unsigned int i;
556
557 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
558 return;
559
560 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
561 tcp->u_nargs = sysent[tcp->scno].nargs;
562 for (i = 0; i < tcp->u_nargs; i++)
563 tcp->u_arg[i] = tcp->u_arg[i + 1];
564}
565#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000566
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200567int
568printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000569{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200570 if (entering(tcp)) {
571 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000572
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200573 for (i = 0; i < tcp->u_nargs; i++)
574 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
575 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000576 return 0;
577}
578
Denys Vlasenko72879c62012-02-27 14:18:02 +0100579int
580printargs_lu(struct tcb *tcp)
581{
582 if (entering(tcp)) {
583 int i;
584
585 for (i = 0; i < tcp->u_nargs; i++)
586 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
587 }
588 return 0;
589}
590
591int
592printargs_ld(struct tcb *tcp)
593{
594 if (entering(tcp)) {
595 int i;
596
597 for (i = 0; i < tcp->u_nargs; i++)
598 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
599 }
600 return 0;
601}
602
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200603long
604getrval2(struct tcb *tcp)
605{
606 long val = -1;
607
Denys Vlasenko523635f2012-02-25 02:44:25 +0100608#if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200609 struct pt_regs regs;
610 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
611 return -1;
612 val = regs.u_regs[U_REG_O1];
613#elif defined(SH)
614 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
615 return -1;
616#elif defined(IA64)
617 if (upeek(tcp, PT_R9, &val) < 0)
618 return -1;
619#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200620
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200621 return val;
622}
623
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200624int
625is_restart_error(struct tcb *tcp)
626{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200627 switch (tcp->u_error) {
628 case ERESTARTSYS:
629 case ERESTARTNOINTR:
630 case ERESTARTNOHAND:
631 case ERESTART_RESTARTBLOCK:
632 return 1;
633 default:
634 break;
635 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200636 return 0;
637}
638
Denys Vlasenko523635f2012-02-25 02:44:25 +0100639#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100640struct pt_regs i386_regs;
H.J. Lu35be5812012-04-16 13:00:01 +0200641#elif defined(X86_64) || defined(X32)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100642/*
643 * On 32 bits, pt_regs and user_regs_struct are the same,
644 * but on 64 bits, user_regs_struct has six more fields:
645 * fs_base, gs_base, ds, es, fs, gs.
646 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
647 */
648static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100649#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200650long r8, r10, psr; /* TODO: make static? */
651long ia32 = 0; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100652#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +0100653static long ppc_result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100654#elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200655static long d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100656#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200657static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100658#elif defined(ARM)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200659static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100660#elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200661static long r0;
662static long a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100663#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200664static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100665#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200666static struct pt_regs regs;
667static unsigned long trap;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100668#elif defined(LINUX_MIPSN32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200669static long long a3;
670static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100671#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200672static long a3;
673static long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100674#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200675static long gpr2;
676static long pc;
677static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100678#elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200679static long r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100680#elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200681static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100682#elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200683static long r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100684#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200685static long r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100686#elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200687static long r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100688#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000689
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200690/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100691 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
692 * 1: ok, continue in trace_syscall_entering().
693 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200694 * ("????" etc) and bail out.
695 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100696static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200697get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000698{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000699 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000700
Denys Vlasenko523635f2012-02-25 02:44:25 +0100701#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000702 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200703 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000704
705 if (syscall_mode != -ENOSYS) {
706 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000707 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000708 */
709 scno = syscall_mode;
710 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000711 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000712 * Old style of "passing" the scno via the SVC instruction.
713 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000714 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200715 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200716 static const int gpr_offset[16] = {
717 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
718 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
719 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
720 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
721 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000722
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000723 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000724 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000725 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000726 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000727 if (errno) {
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000728 perror_msg("%s", "peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000729 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000730 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000731
732 /*
733 * We have to check if the SVC got executed directly or via an
734 * EXECUTE instruction. In case of EXECUTE it is necessary to do
735 * instruction decoding to derive the system call number.
736 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
737 * so that this doesn't work if a SVC opcode is part of an EXECUTE
738 * opcode. Since there is no way to find out the opcode size this
739 * is the best we can do...
740 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000741 if ((opcode & 0xff00) == 0x0a00) {
742 /* SVC opcode */
743 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000744 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000745 else {
746 /* SVC got executed by EXECUTE instruction */
747
748 /*
749 * Do instruction decoding of EXECUTE. If you really want to
750 * understand this, read the Principles of Operations.
751 */
752 svc_addr = (void *) (opcode & 0xfff);
753
754 tmp = 0;
755 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000756 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000757 return -1;
758 svc_addr += tmp;
759
760 tmp = 0;
761 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000762 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000763 return -1;
764 svc_addr += tmp;
765
Denys Vlasenkofb036672009-01-23 16:30:26 +0000766 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000767 if (errno)
768 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100769# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000770 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100771# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000772 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100773# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000774 tmp = 0;
775 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000776 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000777 return -1;
778
779 scno = (scno | tmp) & 0xff;
780 }
781 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100782#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000783 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000784 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100785# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200786 /* TODO: speed up strace by not doing this at every syscall.
787 * We only need to do it after execve.
788 */
789 int currpers;
790 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200791
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200792 /* Check for 64/32 bit mode. */
793 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
794 return -1;
795 /* SF is bit 0 of MSR */
796 if (val < 0)
797 currpers = 0;
798 else
799 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000800 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100801# endif
802#elif defined(AVR32)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200803 /* Read complete register set in one go. */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000804 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
805 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200806 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100807#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000808 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000809 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100810#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200811 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000812 return -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200813 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +0200814#elif defined(X86_64) || defined(X32)
815# ifndef __X32_SYSCALL_BIT
816# define __X32_SYSCALL_BIT 0x40000000
817# endif
818# ifndef __X32_SYSCALL_MASK
819# define __X32_SYSCALL_MASK __X32_SYSCALL_BIT
820# endif
821
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200822 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200823 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
824 return -1;
825 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +0000826
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200827 /* Check CS register value. On x86-64 linux it is:
828 * 0x33 for long mode (64 bit)
829 * 0x23 for compatibility mode (32 bit)
H.J. Lu35be5812012-04-16 13:00:01 +0200830 * Check DS register value. On x86-64 linux it is:
831 * 0x2b for x32 mode (x86-64 in 32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200832 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200833 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200834 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +0200835 case 0x33:
836 if (x86_64_regs.ds == 0x2b) {
837 currpers = 2;
838 scno &= ~__X32_SYSCALL_MASK;
839 } else
840 currpers = 0;
841 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200842 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200843 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200844 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200845 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200846 currpers = current_personality;
847 break;
848 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100849# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200850 /* This version analyzes the opcode of a syscall instruction.
851 * (int 0x80 on i386 vs. syscall on x86-64)
852 * It works, but is too complicated.
853 */
854 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +0000855
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200856 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +0000857
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200858 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
859 rip -= 2;
860 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +0000861
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200862 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200863 if (errno)
864 fprintf(stderr, "ptrace_peektext failed: %s\n",
865 strerror(errno));
866 switch (call & 0xffff) {
867 /* x86-64: syscall = 0x0f 0x05 */
868 case 0x050f: currpers = 0; break;
869 /* i386: int 0x80 = 0xcd 0x80 */
870 case 0x80cd: currpers = 1; break;
871 default:
872 currpers = current_personality;
873 fprintf(stderr,
874 "Unknown syscall opcode (0x%04X) while "
875 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200876 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200877 break;
878 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100879# endif
H.J. Lu35be5812012-04-16 13:00:01 +0200880# ifdef X32
H.J. Lu085e4282012-04-17 11:05:04 -0700881 /* Value of currpers:
882 * 0: 64 bit
883 * 1: 32 bit
884 * 2: X32
885 * Value of current_personality:
886 * 0: X32
887 * 1: 32 bit
888 */
889 switch (currpers) {
890 case 0:
891 fprintf(stderr, "syscall_%lu (...) in unsupported "
892 "64-bit mode of process PID=%d\n",
893 scno, tcp->pid);
894 return 0;
895 case 2:
896 currpers = 0;
H.J. Lu35be5812012-04-16 13:00:01 +0200897 }
H.J. Lu35be5812012-04-16 13:00:01 +0200898# endif
H.J. Lu085e4282012-04-17 11:05:04 -0700899 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100900#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000901# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200902 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000903 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200904 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200905 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200906 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000907 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200908 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000909 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200910 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100911#elif defined(ARM)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200912 /* Read complete register set in one go. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000913 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +0000914 return -1;
915
916 /*
917 * We only need to grab the syscall number on syscall entry.
918 */
919 if (regs.ARM_ip == 0) {
920 /*
921 * Note: we only deal with only 32-bit CPUs here.
922 */
923 if (regs.ARM_cpsr & 0x20) {
924 /*
925 * Get the Thumb-mode system call number
926 */
927 scno = regs.ARM_r7;
928 } else {
929 /*
930 * Get the ARM-mode system call number
931 */
932 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000933 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +0000934 if (errno)
935 return -1;
936
Roland McGrathf691bd22006-04-25 07:34:41 +0000937 /* Handle the EABI syscall convention. We do not
938 bother converting structures between the two
939 ABIs, but basic functionality should work even
940 if strace and the traced program have different
941 ABIs. */
942 if (scno == 0xef000000) {
943 scno = regs.ARM_r7;
944 } else {
945 if ((scno & 0x0ff00000) != 0x0f900000) {
946 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
947 scno);
948 return -1;
949 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000950
Roland McGrathf691bd22006-04-25 07:34:41 +0000951 /*
952 * Fixup the syscall number
953 */
954 scno &= 0x000fffff;
955 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000956 }
Roland McGrath56703312008-05-20 01:35:55 +0000957 if (scno & 0x0f0000) {
958 /*
959 * Handle ARM specific syscall
960 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000961 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +0000962 scno &= 0x0000ffff;
963 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000964 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +0000965
Roland McGrath0f87c492003-06-03 23:29:04 +0000966 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200967 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
968 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000969 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100970#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000971 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000972 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100973#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +0000974 unsigned long long regs[38];
975
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200976 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +0000977 return -1;
978 a3 = regs[REG_A3];
979 r2 = regs[REG_V0];
980
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200981 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200982 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200983 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100984 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200985 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000986 return 0;
987 }
Roland McGrath542c2c62008-05-20 01:11:56 +0000988 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100989#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000990 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000991 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200992 if (upeek(tcp, REG_V0, &scno) < 0)
993 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000994
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200995 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200996 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100997 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200998 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000999 return 0;
1000 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001001 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001002#elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001003 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001004 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001005 if (upeek(tcp, REG_R0, &scno) < 0)
1006 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001007
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001008 /*
1009 * Do some sanity checks to figure out if it's
1010 * really a syscall entry
1011 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001012 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001013 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001014 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001015 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001016 return 0;
1017 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001018 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001019#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001020 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001021 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001022 return -1;
1023
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001024 /* Disassemble the syscall trap. */
1025 /* Retrieve the syscall trap instruction. */
1026 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001027# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001028 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1029 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001030# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001031 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001032# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001033 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001034 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001035
1036 /* Disassemble the trap to see what personality to use. */
1037 switch (trap) {
1038 case 0x91d02010:
1039 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001040 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001041 break;
1042 case 0x91d0206d:
1043 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001044 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001045 break;
1046 case 0x91d02000:
1047 /* SunOS syscall trap. (pers 1) */
1048 fprintf(stderr, "syscall: SunOS no support\n");
1049 return -1;
1050 case 0x91d02008:
1051 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001052 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001053 break;
1054 case 0x91d02009:
1055 /* NetBSD/FreeBSD syscall trap. */
1056 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1057 return -1;
1058 case 0x91d02027:
1059 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001060 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001061 break;
1062 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001063# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001064 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001065# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001066 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001067# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001068 return -1;
1069 }
1070
1071 /* Extract the system call number from the registers. */
1072 if (trap == 0x91d02027)
1073 scno = 156;
1074 else
1075 scno = regs.u_regs[U_REG_G1];
1076 if (scno == 0) {
1077 scno = regs.u_regs[U_REG_O0];
1078 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1079 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001080#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001081 if (upeek(tcp, PT_GR20, &scno) < 0)
1082 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001083#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001084 /*
1085 * In the new syscall ABI, the system call number is in R3.
1086 */
1087 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1088 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001089
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001090 if (scno < 0) {
1091 /* Odd as it may seem, a glibc bug has been known to cause
1092 glibc to issue bogus negative syscall numbers. So for
1093 our purposes, make strace print what it *should* have been */
1094 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001095 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001096 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001097 "Detected glibc bug: bogus system call"
1098 " number = %ld, correcting to %ld\n",
1099 scno,
1100 correct_scno);
1101 scno = correct_scno;
1102 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001103#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001104 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001105 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001106 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001107#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001108 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1109 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001110#elif defined(TILE)
Chris Metcalfc8c66982009-12-28 10:00:15 -05001111 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1112 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001113#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001114 if (upeek(tcp, 0, &scno) < 0)
1115 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001116#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001117
Denys Vlasenko523635f2012-02-25 02:44:25 +01001118#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001119 /* new syscall ABI returns result in R0 */
1120 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1121 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001122#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001123 /* ABI defines result returned in r9 */
1124 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1125 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001126#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001127
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001128 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001129 return 1;
1130}
1131
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001132/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001133 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001134 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1135 * 1: ok, continue in trace_syscall_entering().
1136 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001137 * ("????" etc) and bail out.
1138 */
Roland McGratha4d48532005-06-08 20:45:28 +00001139static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001140syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001141{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001142 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001143#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001144 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001145 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001146 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1147 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001148 }
H.J. Lu35be5812012-04-16 13:00:01 +02001149#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001150 {
1151 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001152 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001153 rax = (int)rax; /* sign extend from 32 bits */
1154 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001155 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001156 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1157 return 0;
1158 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001159 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001160#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001161 /* TODO: we already fetched PT_GPR2 in get_scno
1162 * and stored it in syscall_mode, reuse it here
1163 * instead of re-fetching?
1164 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001165 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001166 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001167 if (syscall_mode != -ENOSYS)
1168 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001169 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001170 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001171 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001172 return 0;
1173 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001174#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001175 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001176 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001177 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001178 if (d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001179 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001180 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001181 return 0;
1182 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001183#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001184 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001185 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001186 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001187 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001188 if (ia32 && r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001189 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001190 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001191 return 0;
1192 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001193#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001194 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001195 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001196 if (r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001197 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001198 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001199 return 0;
1200 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001201#elif defined(MICROBLAZE)
1202 if (upeek(tcp, 3 * 4, &r3) < 0)
1203 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001204 if (r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001205 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001206 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001207 return 0;
1208 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001209#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001210 return 1;
1211}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001212
Denys Vlasenko146b9442012-03-18 22:10:48 +01001213static void
1214internal_fork(struct tcb *tcp)
1215{
1216#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1217# define ARG_FLAGS 1
1218#else
1219# define ARG_FLAGS 0
1220#endif
1221#ifndef CLONE_UNTRACED
1222# define CLONE_UNTRACED 0x00800000
1223#endif
1224 if ((ptrace_setoptions
1225 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1226 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1227 return;
1228
1229 if (!followfork)
1230 return;
1231
1232 if (entering(tcp)) {
1233 /*
1234 * We won't see the new child if clone is called with
1235 * CLONE_UNTRACED, so we keep the same logic with that option
1236 * and don't trace it.
1237 */
1238 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1239 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1240 return;
1241 setbpt(tcp);
1242 } else {
1243 if (tcp->flags & TCB_BPTSET)
1244 clearbpt(tcp);
1245 }
1246}
1247
1248#if defined(TCB_WAITEXECVE)
1249static void
1250internal_exec(struct tcb *tcp)
1251{
1252 /* Maybe we have post-execve SIGTRAP suppressed? */
1253 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1254 return; /* yes, no need to do anything */
1255
1256 if (exiting(tcp) && syserror(tcp))
1257 /* Error in execve, no post-execve SIGTRAP expected */
1258 tcp->flags &= ~TCB_WAITEXECVE;
1259 else
1260 tcp->flags |= TCB_WAITEXECVE;
1261}
1262#endif
1263
1264static void
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001265internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001266{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001267 /*
1268 * We must always trace a few critical system calls in order to
1269 * correctly support following forks in the presence of tracing
1270 * qualifiers.
1271 */
1272 int (*func)();
1273
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001274 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001275 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001276
1277 func = sysent[tcp->scno].sys_func;
1278
1279 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001280 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001281 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001282 ) {
1283 internal_fork(tcp);
1284 return;
1285 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001286
Denys Vlasenko84703742012-02-25 02:38:52 +01001287#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001288 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001289# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001290 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001291# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001292 ) {
1293 internal_exec(tcp);
1294 return;
1295 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001296#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001297}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001298
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001299/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001300static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001301get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001302{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001303 int i, nargs;
1304
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001305 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001306 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001307 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001308 nargs = tcp->u_nargs = MAX_ARGS;
1309
Denys Vlasenko523635f2012-02-25 02:44:25 +01001310#if defined(S390) || defined(S390X)
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, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1313 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001314#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001315 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001316 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1317 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001318#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001319 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001320 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001321 long rbs_end;
1322 /* be backwards compatible with kernel < 2.4.4... */
1323# ifndef PT_RBS_END
1324# define PT_RBS_END PT_AR_BSP
1325# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001326
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001327 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1328 return -1;
1329 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001330 return -1;
1331
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001332 sof = (cfm >> 0) & 0x7f;
1333 sol = (cfm >> 7) & 0x7f;
1334 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1335
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001336 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001337 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1338 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1339 return -1;
1340 }
1341 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001342 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1343 PT_R9 /* ECX = out1 */,
1344 PT_R10 /* EDX = out2 */,
1345 PT_R14 /* ESI = out3 */,
1346 PT_R15 /* EDI = out4 */,
1347 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001348
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001349 for (i = 0; i < nargs; ++i) {
1350 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1351 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001352 /* truncate away IVE sign-extension */
1353 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001354 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001355 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001356#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001357 /* N32 and N64 both use up to six registers. */
1358 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001359
1360 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1361 return -1;
1362
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001363 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001364 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001365# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001366 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001367# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001368 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001369#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001370 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001371 long sp;
1372
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001373 if (upeek(tcp, REG_SP, &sp) < 0)
1374 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001375 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001376 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1377 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001378 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001379 (char *)(tcp->u_arg + 4));
1380 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001381 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001382 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001383 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001384 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001385#elif defined(POWERPC)
1386# ifndef PT_ORIG_R3
1387# define PT_ORIG_R3 34
1388# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001389 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001390 if (upeek(tcp, (i==0) ?
1391 (sizeof(unsigned long) * PT_ORIG_R3) :
1392 ((i+PT_R3) * sizeof(unsigned long)),
1393 &tcp->u_arg[i]) < 0)
1394 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001395 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001396#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001397 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001398 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001399#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001400 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001401 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1402 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001403#elif defined(ARM)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001404 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001405 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001406#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001407 (void)i;
1408 (void)nargs;
1409 tcp->u_arg[0] = regs.r12;
1410 tcp->u_arg[1] = regs.r11;
1411 tcp->u_arg[2] = regs.r10;
1412 tcp->u_arg[3] = regs.r9;
1413 tcp->u_arg[4] = regs.r5;
1414 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001415#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001416 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 +02001417
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001418 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001419 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1420 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001421#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001422 static const int syscall_regs[MAX_ARGS] = {
1423 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1424 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001425 };
1426
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001427 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001428 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001429 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001430#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001431 int i;
1432 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001433 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001434
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001435 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001436 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1437 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001438#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001439 (void)i;
1440 (void)nargs;
H.J. Lu35be5812012-04-16 13:00:01 +02001441 if (current_personality != 1) { /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001442 tcp->u_arg[0] = x86_64_regs.rdi;
1443 tcp->u_arg[1] = x86_64_regs.rsi;
1444 tcp->u_arg[2] = x86_64_regs.rdx;
1445 tcp->u_arg[3] = x86_64_regs.r10;
1446 tcp->u_arg[4] = x86_64_regs.r8;
1447 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001448# ifdef X32
1449 tcp->ext_arg[0] = x86_64_regs.rdi;
1450 tcp->ext_arg[1] = x86_64_regs.rsi;
1451 tcp->ext_arg[2] = x86_64_regs.rdx;
1452 tcp->ext_arg[3] = x86_64_regs.r10;
1453 tcp->ext_arg[4] = x86_64_regs.r8;
1454 tcp->ext_arg[5] = x86_64_regs.r9;
1455# endif
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001456 } else { /* i386 ABI */
1457 /* Sign-extend lower 32 bits */
1458 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1459 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1460 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1461 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1462 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1463 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1464 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001465#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001466 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001467 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1468 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001469#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001470 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001471 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001472 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001473 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001474
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, crisregs[i], &tcp->u_arg[i]) < 0)
1477 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001478#elif defined(TILE)
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, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1481 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001482#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001483 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001484 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1485 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001486#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001487 (void)i;
1488 (void)nargs;
1489 tcp->u_arg[0] = i386_regs.ebx;
1490 tcp->u_arg[1] = i386_regs.ecx;
1491 tcp->u_arg[2] = i386_regs.edx;
1492 tcp->u_arg[3] = i386_regs.esi;
1493 tcp->u_arg[4] = i386_regs.edi;
1494 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001495#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001496 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001497 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1498 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001499#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001500 return 1;
1501}
1502
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001503static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001504trace_syscall_entering(struct tcb *tcp)
1505{
1506 int res, scno_good;
1507
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001508#if defined TCB_WAITEXECVE
1509 if (tcp->flags & TCB_WAITEXECVE) {
1510 /* This is the post-execve SIGTRAP. */
1511 tcp->flags &= ~TCB_WAITEXECVE;
1512 return 0;
1513 }
1514#endif
1515
Denys Vlasenko06602d92011-08-24 17:53:52 +02001516 scno_good = res = get_scno(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001517 if (res == 0)
1518 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001519 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001520 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001521 if (res == 0)
1522 return res;
1523 if (res == 1)
1524 res = get_syscall_args(tcp);
1525 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001526
1527 if (res != 1) {
1528 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001529 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001530 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001531 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001532 tprintf("syscall_%lu(", tcp->scno);
1533 else
1534 tprintf("%s(", sysent[tcp->scno].sys_name);
1535 /*
1536 * " <unavailable>" will be added later by the code which
1537 * detects ptrace errors.
1538 */
1539 goto ret;
1540 }
1541
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001542#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1543 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001544# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001545 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001546 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001547 break;
1548 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001549# endif
1550# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001551 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001552 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001553 break;
1554 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001555# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001556 break;
1557 }
1558#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1559
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001560 internal_syscall(tcp);
1561
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001562 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001563 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1564 (tracing_paths && !pathtrace_match(tcp))) {
1565 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1566 return 0;
1567 }
1568
1569 tcp->flags &= ~TCB_FILTERED;
1570
1571 if (cflag == CFLAG_ONLY_STATS) {
1572 res = 0;
1573 goto ret;
1574 }
1575
1576 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001577 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001578 tprintf("syscall_%lu(", tcp->scno);
1579 else
1580 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001581 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001582 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1583 sysent[tcp->scno].sys_func != sys_exit))
1584 res = printargs(tcp);
1585 else
1586 res = (*sysent[tcp->scno].sys_func)(tcp);
1587
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001588 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001589 ret:
1590 tcp->flags |= TCB_INSYSCALL;
1591 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001592 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001593 gettimeofday(&tcp->etime, NULL);
1594 return res;
1595}
1596
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001597/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001598 * 1: ok, continue in trace_syscall_exiting().
1599 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001600 * ("????" etc) and bail out.
1601 */
1602static int
1603get_syscall_result(struct tcb *tcp)
1604{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001605#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001606 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1607 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001608#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001609# define SO_MASK 0x10000000
1610 {
1611 long flags;
1612 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1613 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001614 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001615 return -1;
1616 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001617 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001618 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001619#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001620 /* Read complete register set in one go. */
1621 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1622 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001623#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001624 if (upeek(tcp, PT_R0, &r0) < 0)
1625 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001626#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001627 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001628 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001629#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001630 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001631 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001632#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001633# define IA64_PSR_IS ((long)1 << 34)
1634 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1635 ia32 = (psr & IA64_PSR_IS) != 0;
1636 if (upeek(tcp, PT_R8, &r8) < 0)
1637 return -1;
1638 if (upeek(tcp, PT_R10, &r10) < 0)
1639 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001640#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001641 /* Read complete register set in one go. */
1642 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1643 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001644#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001645 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1646 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001647#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001648 unsigned long long regs[38];
1649
1650 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1651 return -1;
1652 a3 = regs[REG_A3];
1653 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001654#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001655 if (upeek(tcp, REG_A3, &a3) < 0)
1656 return -1;
1657 if (upeek(tcp, REG_V0, &r2) < 0)
1658 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001659#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001660 if (upeek(tcp, REG_A3, &a3) < 0)
1661 return -1;
1662 if (upeek(tcp, REG_R0, &r0) < 0)
1663 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001664#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001665 /* Everything we need is in the current register set. */
1666 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1667 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001668#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001669 if (upeek(tcp, PT_GR28, &r28) < 0)
1670 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001671#elif defined(SH)
1672#elif defined(SH64)
1673#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001674 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1675 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001676#elif defined(TILE)
1677#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001678 if (upeek(tcp, 3 * 4, &r3) < 0)
1679 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001680#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001681
Denys Vlasenko523635f2012-02-25 02:44:25 +01001682#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001683 /* new syscall ABI returns result in R0 */
1684 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1685 return -1;
1686#elif defined(SH64)
1687 /* ABI defines result returned in r9 */
1688 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1689 return -1;
1690#endif
1691
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001692 return 1;
1693}
1694
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001695/* Called at each syscall exit */
1696static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001697syscall_fixup_on_sysexit(struct tcb *tcp)
1698{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001699#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001700 if (syscall_mode != -ENOSYS)
1701 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001702 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001703 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1704 /*
1705 * Return from execve.
1706 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1707 * flag set for the post-execve SIGTRAP to see and reset.
1708 */
1709 gpr2 = 0;
1710 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001711#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001712}
1713
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001714/*
1715 * Check the syscall return value register value for whether it is
1716 * a negated errno code indicating an error, or a success return value.
1717 */
1718static inline int
1719is_negated_errno(unsigned long int val)
1720{
1721 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001722#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001723 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001724 val = (unsigned int) val;
1725 max = (unsigned int) max;
1726 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001727#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001728 return val > max;
1729}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001730
Denys Vlasenko907735a2012-03-21 00:23:16 +01001731/* Returns:
1732 * 1: ok, continue in trace_syscall_exiting().
1733 * -1: error, trace_syscall_exiting() should print error indicator
1734 * ("????" etc) and bail out.
1735 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001736static int
1737get_error(struct tcb *tcp)
1738{
1739 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001740 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001741 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001742 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1743 check_errno = 0;
1744 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001745#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001746 if (check_errno && is_negated_errno(gpr2)) {
1747 tcp->u_rval = -1;
1748 u_error = -gpr2;
1749 }
1750 else {
1751 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001752 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001753#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001754 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001755 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001756 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001757 }
1758 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001759 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001760 }
H.J. Lu35be5812012-04-16 13:00:01 +02001761#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001762 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001763 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001764 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001765 }
1766 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001767 tcp->u_rval = x86_64_regs.rax;
H.J. Lu35be5812012-04-16 13:00:01 +02001768# if defined(X32)
1769 tcp->u_lrval = x86_64_regs.rax;
1770# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001771 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001772#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001773 if (ia32) {
1774 int err;
1775
1776 err = (int)r8;
1777 if (check_errno && is_negated_errno(err)) {
1778 tcp->u_rval = -1;
1779 u_error = -err;
1780 }
1781 else {
1782 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001783 }
1784 } else {
1785 if (check_errno && r10) {
1786 tcp->u_rval = -1;
1787 u_error = r8;
1788 } else {
1789 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001790 }
1791 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001792#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001793 if (check_errno && a3) {
1794 tcp->u_rval = -1;
1795 u_error = r2;
1796 } else {
1797 tcp->u_rval = r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02001798# if defined(LINUX_MIPSN32)
1799 tcp->u_lrval = r2;
1800# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001801 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001802#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001803 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001804 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001805 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001806 }
1807 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001808 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001809 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001810#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001811 if (check_errno && is_negated_errno(d0)) {
1812 tcp->u_rval = -1;
1813 u_error = -d0;
1814 }
1815 else {
1816 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001817 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001818#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001819 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1820 tcp->u_rval = -1;
1821 u_error = -regs.ARM_r0;
1822 }
1823 else {
1824 tcp->u_rval = regs.ARM_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001825 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001826#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001827 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1828 tcp->u_rval = -1;
1829 u_error = -regs.r12;
1830 }
1831 else {
1832 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001833 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001834#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001835 if (check_errno && is_negated_errno(r0)) {
1836 tcp->u_rval = -1;
1837 u_error = -r0;
1838 } else {
1839 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001840 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001841#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001842 if (check_errno && a3) {
1843 tcp->u_rval = -1;
1844 u_error = r0;
1845 }
1846 else {
1847 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001848 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001849#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001850 if (check_errno && regs.psr & PSR_C) {
1851 tcp->u_rval = -1;
1852 u_error = regs.u_regs[U_REG_O0];
1853 }
1854 else {
1855 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001856 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001857#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001858 if (check_errno && regs.tstate & 0x1100000000UL) {
1859 tcp->u_rval = -1;
1860 u_error = regs.u_regs[U_REG_O0];
1861 }
1862 else {
1863 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001864 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001865#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001866 if (check_errno && is_negated_errno(r28)) {
1867 tcp->u_rval = -1;
1868 u_error = -r28;
1869 }
1870 else {
1871 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001872 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001873#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001874 if (check_errno && is_negated_errno(r0)) {
1875 tcp->u_rval = -1;
1876 u_error = -r0;
1877 }
1878 else {
1879 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001880 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001881#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001882 if (check_errno && is_negated_errno(r9)) {
1883 tcp->u_rval = -1;
1884 u_error = -r9;
1885 }
1886 else {
1887 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001888 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001889#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001890 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1891 tcp->u_rval = -1;
1892 u_error = -r10;
1893 }
1894 else {
1895 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001896 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001897#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001898 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001899 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1900 return -1;
1901 if (check_errno && rval < 0 && rval > -nerrnos) {
1902 tcp->u_rval = -1;
1903 u_error = -rval;
1904 }
1905 else {
1906 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001907 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001908#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001909 if (check_errno && is_negated_errno(r3)) {
1910 tcp->u_rval = -1;
1911 u_error = -r3;
1912 }
1913 else {
1914 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001915 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001916#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001917 tcp->u_error = u_error;
1918 return 1;
1919}
1920
1921static void
1922dumpio(struct tcb *tcp)
1923{
1924 if (syserror(tcp))
1925 return;
1926 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1927 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001928 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001929 return;
1930 if (sysent[tcp->scno].sys_func == printargs)
1931 return;
1932 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1933 if (sysent[tcp->scno].sys_func == sys_read ||
1934 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001935 sysent[tcp->scno].sys_func == sys_recv ||
1936 sysent[tcp->scno].sys_func == sys_recvfrom)
1937 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1938 else if (sysent[tcp->scno].sys_func == sys_readv)
1939 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1940 return;
1941 }
1942 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1943 if (sysent[tcp->scno].sys_func == sys_write ||
1944 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001945 sysent[tcp->scno].sys_func == sys_send ||
1946 sysent[tcp->scno].sys_func == sys_sendto)
1947 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1948 else if (sysent[tcp->scno].sys_func == sys_writev)
1949 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1950 return;
1951 }
1952}
1953
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001954static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001955trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001956{
1957 int sys_res;
1958 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001959 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001960 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001961
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001962 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001963 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001964 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001965
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001966#if SUPPORTED_PERSONALITIES > 1
1967 update_personality(tcp, tcp->currpers);
1968#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001969 res = get_syscall_result(tcp);
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001970 if (res == 1) {
1971 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01001972 res = get_error(tcp); /* returns 1 or -1 */
1973 if (res == 1) {
1974 internal_syscall(tcp);
1975 if (filtered(tcp)) {
1976 goto ret;
1977 }
1978 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00001979 }
1980
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001981 if (cflag) {
1982 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02001983 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02001984 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001985 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001986 }
1987 }
1988
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01001989 /* If not in -ff mode, and printing_tcp != tcp,
1990 * then the log currently does not end with output
1991 * of _our syscall entry_, but with something else.
1992 * We need to say which syscall's return is this.
1993 *
1994 * Forced reprinting via TCB_REPRINT is used only by
1995 * "strace -ff -oLOG test/threaded_execve" corner case.
1996 * It's the only case when -ff mode needs reprinting.
1997 */
1998 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
1999 tcp->flags &= ~TCB_REPRINT;
2000 printleader(tcp);
2001 if (!SCNO_IN_RANGE(tcp->scno))
2002 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2003 else
2004 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2005 }
2006 printing_tcp = tcp;
2007
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002008 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002009 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002010 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002011 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002012 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002013 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002014 tcp->flags &= ~TCB_INSYSCALL;
2015 return res;
2016 }
2017
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002018 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002019 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002020 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002021 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002022 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002023 /* FIXME: not_failing_only (IOW, option -z) is broken:
2024 * failure of syscall is known only after syscall return.
2025 * Thus we end up with something like this on, say, ENOENT:
2026 * open("doesnt_exist", O_RDONLY <unfinished ...>
2027 * {next syscall decode}
2028 * whereas the intended result is that open(...) line
2029 * is not shown at all.
2030 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002031 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002032 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002033 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2034 }
2035
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002036 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002037 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002038 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002039 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002040 qual_flags[tcp->scno] & QUAL_RAW) {
2041 if (u_error)
2042 tprintf("= -1 (errno %ld)", u_error);
2043 else
2044 tprintf("= %#lx", tcp->u_rval);
2045 }
2046 else if (!(sys_res & RVAL_NONE) && u_error) {
2047 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002048 /* Blocked signals do not interrupt any syscalls.
2049 * In this case syscalls don't return ERESTARTfoo codes.
2050 *
2051 * Deadly signals set to SIG_DFL interrupt syscalls
2052 * and kill the process regardless of which of the codes below
2053 * is returned by the interrupted syscall.
2054 * In some cases, kernel forces a kernel-generated deadly
2055 * signal to be unblocked and set to SIG_DFL (and thus cause
2056 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2057 * or SIGILL. (The alternative is to leave process spinning
2058 * forever on the faulty instruction - not useful).
2059 *
2060 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2061 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2062 * but kernel will always restart them.
2063 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002064 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002065 /* Most common type of signal-interrupted syscall exit code.
2066 * The system call will be restarted with the same arguments
2067 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2068 */
2069 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002070 break;
2071 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002072 /* Rare. For example, fork() returns this if interrupted.
2073 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2074 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002075 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002076 break;
2077 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002078 /* pause(), rt_sigsuspend() etc use this code.
2079 * SA_RESTART is ignored (assumed not set):
2080 * syscall won't restart (will return EINTR instead)
2081 * even after signal with SA_RESTART set.
2082 * However, after SIG_IGN or SIG_DFL signal it will.
2083 */
2084 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002085 break;
2086 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002087 /* Syscalls like nanosleep(), poll() which can't be
2088 * restarted with their original arguments use this
2089 * code. Kernel will execute restart_syscall() instead,
2090 * which changes arguments before restarting syscall.
2091 * SA_RESTART is ignored (assumed not set) similarly
2092 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2093 * since restart data is saved in "restart block"
2094 * in task struct, and if signal handler uses a syscall
2095 * which in turn saves another such restart block,
2096 * old data is lost and restart becomes impossible)
2097 */
2098 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002099 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002100 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002101 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002102 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002103 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002104 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002105 strerror(u_error));
2106 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002107 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002108 strerror(u_error));
2109 break;
2110 }
2111 if ((sys_res & RVAL_STR) && tcp->auxstr)
2112 tprintf(" (%s)", tcp->auxstr);
2113 }
2114 else {
2115 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002116 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002117 else {
2118 switch (sys_res & RVAL_MASK) {
2119 case RVAL_HEX:
2120 tprintf("= %#lx", tcp->u_rval);
2121 break;
2122 case RVAL_OCTAL:
2123 tprintf("= %#lo", tcp->u_rval);
2124 break;
2125 case RVAL_UDECIMAL:
2126 tprintf("= %lu", tcp->u_rval);
2127 break;
2128 case RVAL_DECIMAL:
2129 tprintf("= %ld", tcp->u_rval);
2130 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002131#if defined(LINUX_MIPSN32) || defined(X32)
2132 /*
2133 case RVAL_LHEX:
2134 tprintf("= %#llx", tcp->u_lrval);
2135 break;
2136 case RVAL_LOCTAL:
2137 tprintf("= %#llo", tcp->u_lrval);
2138 break;
2139 */
2140 case RVAL_LUDECIMAL:
2141 tprintf("= %llu", tcp->u_lrval);
2142 break;
2143 /*
2144 case RVAL_LDECIMAL:
2145 tprintf("= %lld", tcp->u_lrval);
2146 break;
2147 */
2148#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002149 default:
2150 fprintf(stderr,
2151 "invalid rval format\n");
2152 break;
2153 }
2154 }
2155 if ((sys_res & RVAL_STR) && tcp->auxstr)
2156 tprintf(" (%s)", tcp->auxstr);
2157 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002158 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002159 tv_sub(&tv, &tv, &tcp->etime);
2160 tprintf(" <%ld.%06ld>",
2161 (long) tv.tv_sec, (long) tv.tv_usec);
2162 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002163 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002164 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002165 line_ended();
2166
Denys Vlasenko3b738812011-08-22 02:06:35 +02002167 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002168 tcp->flags &= ~TCB_INSYSCALL;
2169 return 0;
2170}
2171
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002172int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002173trace_syscall(struct tcb *tcp)
2174{
2175 return exiting(tcp) ?
2176 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2177}