blob: 680cbc39002309c14225f898dcc7eec3c8657cb8 [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
Steve McIntyred8d3bd32012-10-24 17:58:16 +010068#if defined(AARCH64)
69# include <asm/ptrace.h>
70# include <sys/uio.h>
71# include <elf.h>
72#endif
73
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000074#ifndef ERESTARTSYS
Denys Vlasenko523635f2012-02-25 02:44:25 +010075# define ERESTARTSYS 512
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000076#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010077#ifndef ERESTARTNOINTR
Denys Vlasenko523635f2012-02-25 02:44:25 +010078# define ERESTARTNOINTR 513
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000079#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010080#ifndef ERESTARTNOHAND
81# define ERESTARTNOHAND 514 /* restart if no handler */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000082#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010083#ifndef ERESTART_RESTARTBLOCK
Denys Vlasenko523635f2012-02-25 02:44:25 +010084# define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
Roland McGrath9c555e72003-07-09 09:47:59 +000085#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010086
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000087#ifndef NSIG
Denys Vlasenko523635f2012-02-25 02:44:25 +010088# warning: NSIG is not defined, using 32
89# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000090#endif
91#ifdef ARM
Denys Vlasenko041b3ee2011-08-18 12:48:56 +020092/* Ugh. Is this really correct? ARM has no RT signals?! */
Denys Vlasenko523635f2012-02-25 02:44:25 +010093# undef NSIG
94# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000095#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000096
97#include "syscall.h"
98
99/* Define these shorthand notations to simplify the syscallent files. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000100#define TD TRACE_DESC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000101#define TF TRACE_FILE
102#define TI TRACE_IPC
103#define TN TRACE_NETWORK
104#define TP TRACE_PROCESS
105#define TS TRACE_SIGNAL
Namhyung Kim96792962012-10-24 11:41:57 +0900106#define TM TRACE_MEMORY
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000107#define NF SYSCALL_NEVER_FAILS
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200108#define MA MAX_ARGS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000109
Roland McGrathee36ce12004-09-04 03:53:10 +0000110static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000111#include "syscallent.h"
112};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000113
114#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000115static const struct sysent sysent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100116# include "syscallent1.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#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000121static const struct sysent sysent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100122# include "syscallent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000123};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200124#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000125
126/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000127#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000128#undef TF
129#undef TI
130#undef TN
131#undef TP
132#undef TS
Namhyung Kim96792962012-10-24 11:41:57 +0900133#undef TM
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000134#undef NF
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200135#undef MA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000136
Denys Vlasenko39fca622011-08-20 02:12:33 +0200137/*
138 * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
139 * program `ioctlsort', such that the list is sorted by the `code' field.
140 * This has the side-effect of resolving the _IO.. macros into
141 * plain integers, eliminating the need to include here everything
142 * in "/usr/include".
143 */
144
Roland McGrathee36ce12004-09-04 03:53:10 +0000145static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000146#include "errnoent.h"
147};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200148static const char *const signalent0[] = {
149#include "signalent.h"
150};
151static const struct ioctlent ioctlent0[] = {
152#include "ioctlent.h"
153};
154enum { nsyscalls0 = ARRAY_SIZE(sysent0) };
155enum { nerrnos0 = ARRAY_SIZE(errnoent0) };
156enum { nsignals0 = ARRAY_SIZE(signalent0) };
157enum { nioctlents0 = ARRAY_SIZE(ioctlent0) };
158int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000159
160#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000161static const char *const errnoent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100162# include "errnoent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000163};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200164static const char *const signalent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100165# include "signalent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200166};
167static const struct ioctlent ioctlent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100168# include "ioctlent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200169};
170enum { nsyscalls1 = ARRAY_SIZE(sysent1) };
171enum { nerrnos1 = ARRAY_SIZE(errnoent1) };
172enum { nsignals1 = ARRAY_SIZE(signalent1) };
173enum { nioctlents1 = ARRAY_SIZE(ioctlent1) };
174int qual_flags1[MAX_QUALS];
175#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000176
177#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000178static const char *const errnoent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100179# include "errnoent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000180};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200181static const char *const signalent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100182# include "signalent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200183};
184static const struct ioctlent ioctlent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100185# include "ioctlent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200186};
187enum { nsyscalls2 = ARRAY_SIZE(sysent2) };
188enum { nerrnos2 = ARRAY_SIZE(errnoent2) };
189enum { nsignals2 = ARRAY_SIZE(signalent2) };
190enum { nioctlents2 = ARRAY_SIZE(ioctlent2) };
191int qual_flags2[MAX_QUALS];
192#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000193
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100194const struct sysent *sysent = sysent0;
195const char *const *errnoent = errnoent0;
196const char *const *signalent = signalent0;
197const struct ioctlent *ioctlent = ioctlent0;
198unsigned nsyscalls = nsyscalls0;
199unsigned nerrnos = nerrnos0;
200unsigned nsignals = nsignals0;
201unsigned nioctlents = nioctlents0;
202int *qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000203
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100204#if SUPPORTED_PERSONALITIES > 1
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000205int current_personality;
206
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000207const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
208 PERSONALITY0_WORDSIZE,
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000209 PERSONALITY1_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100210# if SUPPORTED_PERSONALITIES > 2
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000211 PERSONALITY2_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100212# endif
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200213};
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000214
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200215void
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000216set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000217{
218 switch (personality) {
219 case 0:
220 errnoent = errnoent0;
221 nerrnos = nerrnos0;
222 sysent = sysent0;
223 nsyscalls = nsyscalls0;
224 ioctlent = ioctlent0;
225 nioctlents = nioctlents0;
226 signalent = signalent0;
227 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000228 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000229 break;
230
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000231 case 1:
232 errnoent = errnoent1;
233 nerrnos = nerrnos1;
234 sysent = sysent1;
235 nsyscalls = nsyscalls1;
236 ioctlent = ioctlent1;
237 nioctlents = nioctlents1;
238 signalent = signalent1;
239 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000240 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000241 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000242
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100243# if SUPPORTED_PERSONALITIES >= 3
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000244 case 2:
245 errnoent = errnoent2;
246 nerrnos = nerrnos2;
247 sysent = sysent2;
248 nsyscalls = nsyscalls2;
249 ioctlent = ioctlent2;
250 nioctlents = nioctlents2;
251 signalent = signalent2;
252 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000253 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000254 break;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100255# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000256 }
257
258 current_personality = personality;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000259}
260
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000261static void
262update_personality(struct tcb *tcp, int personality)
263{
264 if (personality == current_personality)
265 return;
266 set_personality(personality);
267
268 if (personality == tcp->currpers)
269 return;
270 tcp->currpers = personality;
271
H.J. Lu35be5812012-04-16 13:00:01 +0200272# if defined(POWERPC64)
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000273 if (!qflag) {
274 static const char *const names[] = {"64 bit", "32 bit"};
275 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
276 tcp->pid, names[personality]);
277 }
H.J. Lu35be5812012-04-16 13:00:01 +0200278# elif defined(X86_64)
279 if (!qflag) {
280 static const char *const names[] = {"64 bit", "32 bit", "x32"};
281 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
282 tcp->pid, names[personality]);
283 }
H.J. Lu085e4282012-04-17 11:05:04 -0700284# elif defined(X32)
285 if (!qflag) {
286 static const char *const names[] = {"x32", "32 bit"};
287 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
288 tcp->pid, names[personality]);
289 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100290# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000291}
292#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000293
Roland McGrath9797ceb2002-12-30 10:23:00 +0000294static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000295
Roland McGrathe10e62a2004-09-04 04:20:43 +0000296static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000297 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000298 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000299 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000300 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000301} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000302 { QUAL_TRACE, "trace", qual_syscall, "system call" },
303 { QUAL_TRACE, "t", qual_syscall, "system call" },
304 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
305 { QUAL_ABBREV, "a", qual_syscall, "system call" },
306 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
307 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
308 { QUAL_RAW, "raw", qual_syscall, "system call" },
309 { QUAL_RAW, "x", qual_syscall, "system call" },
310 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
311 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
312 { QUAL_SIGNAL, "s", qual_signal, "signal" },
313 { QUAL_FAULT, "fault", qual_fault, "fault" },
314 { QUAL_FAULT, "faults", qual_fault, "fault" },
315 { QUAL_FAULT, "m", qual_fault, "fault" },
316 { QUAL_READ, "read", qual_desc, "descriptor" },
317 { QUAL_READ, "reads", qual_desc, "descriptor" },
318 { QUAL_READ, "r", qual_desc, "descriptor" },
319 { QUAL_WRITE, "write", qual_desc, "descriptor" },
320 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
321 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000322 { 0, NULL, NULL, NULL },
323};
324
Roland McGrath9797ceb2002-12-30 10:23:00 +0000325static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000326qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000327{
Roland McGrath138c6a32006-01-12 09:50:49 +0000328 if (pers == 0 || pers < 0) {
329 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000330 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000331 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000332 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000333 }
334
335#if SUPPORTED_PERSONALITIES >= 2
336 if (pers == 1 || pers < 0) {
337 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000338 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000339 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000340 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000341 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100342#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000343
344#if SUPPORTED_PERSONALITIES >= 3
345 if (pers == 2 || pers < 0) {
346 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000347 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000348 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000349 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000350 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100351#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000352}
353
354static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000355qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000356{
357 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000358 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000359
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100360 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000361 int i = string_to_uint(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000362 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000363 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000364 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000365 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000366 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000367 for (i = 0; i < nsyscalls0; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000368 if (sysent0[i].sys_name &&
369 strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000370 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000371 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000372 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000373
374#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000375 for (i = 0; i < nsyscalls1; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000376 if (sysent1[i].sys_name &&
377 strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000378 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000379 rc = 0;
380 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100381#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000382
383#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000384 for (i = 0; i < nsyscalls2; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000385 if (sysent2[i].sys_name &&
386 strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000387 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000388 rc = 0;
389 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100390#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000391
Roland McGrathfe6b3522005-02-02 04:40:11 +0000392 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000393}
394
395static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000396qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000397{
398 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000399
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100400 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000401 int signo = string_to_uint(s);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000402 if (signo < 0 || signo >= MAX_QUALS)
403 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000404 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000405 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000406 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000407 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000408 s += 3;
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100409 for (i = 0; i <= NSIG; i++) {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000410 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000411 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000412 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000413 }
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100414 }
Roland McGrath76421df2005-02-02 03:51:18 +0000415 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000416}
417
418static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000419qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000420{
421 return -1;
422}
423
424static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000425qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000426{
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100427 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000428 int desc = string_to_uint(s);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000429 if (desc < 0 || desc >= MAX_QUALS)
430 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000431 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000432 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000433 }
434 return -1;
435}
436
437static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000438lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000439{
440 if (strcmp(s, "file") == 0)
441 return TRACE_FILE;
442 if (strcmp(s, "ipc") == 0)
443 return TRACE_IPC;
444 if (strcmp(s, "network") == 0)
445 return TRACE_NETWORK;
446 if (strcmp(s, "process") == 0)
447 return TRACE_PROCESS;
448 if (strcmp(s, "signal") == 0)
449 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000450 if (strcmp(s, "desc") == 0)
451 return TRACE_DESC;
Namhyung Kim96792962012-10-24 11:41:57 +0900452 if (strcmp(s, "memory") == 0)
453 return TRACE_MEMORY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000454 return -1;
455}
456
457void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000458qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000459{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000460 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000461 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000462 char *copy;
463 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000464 int i, n;
465
466 opt = &qual_options[0];
467 for (i = 0; (p = qual_options[i].option_name); i++) {
468 n = strlen(p);
469 if (strncmp(s, p, n) == 0 && s[n] == '=') {
470 opt = &qual_options[i];
471 s += n + 1;
472 break;
473 }
474 }
475 not = 0;
476 if (*s == '!') {
477 not = 1;
478 s++;
479 }
480 if (strcmp(s, "none") == 0) {
481 not = 1 - not;
482 s = "all";
483 }
484 if (strcmp(s, "all") == 0) {
485 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000486 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000487 }
488 return;
489 }
490 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000491 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000492 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200493 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200494 if (!copy)
495 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000496 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000497 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000498 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000499 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000500 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000501
502#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000503 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000504 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000505 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100506#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000507
508#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000509 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000510 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000511 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100512#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000513
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000514 continue;
515 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000516 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100517 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000518 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000519 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000520 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000521 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000522 return;
523}
524
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000525#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000526static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000527decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000528{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000529 unsigned long addr;
530 unsigned int i, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000531
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000532 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
533 return;
534
535 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
536 addr = tcp->u_arg[1];
537 tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100538 size = current_wordsize;
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000539 for (i = 0; i < tcp->u_nargs; ++i) {
540 if (size == sizeof(int)) {
541 unsigned int arg;
542 if (umove(tcp, addr, &arg) < 0)
543 arg = 0;
544 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000545 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000546 else {
547 unsigned long arg;
548 if (umove(tcp, addr, &arg) < 0)
549 arg = 0;
550 tcp->u_arg[i] = arg;
551 }
552 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000553 }
554}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000555#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400556
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000557#ifdef SYS_ipc_subcall
558static void
559decode_ipc_subcall(struct tcb *tcp)
560{
561 unsigned int i;
562
563 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
564 return;
565
566 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
567 tcp->u_nargs = sysent[tcp->scno].nargs;
568 for (i = 0; i < tcp->u_nargs; i++)
569 tcp->u_arg[i] = tcp->u_arg[i + 1];
570}
571#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000572
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200573int
574printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000575{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200576 if (entering(tcp)) {
577 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000578
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200579 for (i = 0; i < tcp->u_nargs; i++)
580 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
581 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000582 return 0;
583}
584
Denys Vlasenko72879c62012-02-27 14:18:02 +0100585int
586printargs_lu(struct tcb *tcp)
587{
588 if (entering(tcp)) {
589 int i;
590
591 for (i = 0; i < tcp->u_nargs; i++)
592 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
593 }
594 return 0;
595}
596
597int
598printargs_ld(struct tcb *tcp)
599{
600 if (entering(tcp)) {
601 int i;
602
603 for (i = 0; i < tcp->u_nargs; i++)
604 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
605 }
606 return 0;
607}
608
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200609long
610getrval2(struct tcb *tcp)
611{
612 long val = -1;
613
Denys Vlasenko523635f2012-02-25 02:44:25 +0100614#if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200615 struct pt_regs regs;
616 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
617 return -1;
618 val = regs.u_regs[U_REG_O1];
619#elif defined(SH)
620 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
621 return -1;
622#elif defined(IA64)
623 if (upeek(tcp, PT_R9, &val) < 0)
624 return -1;
625#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200626
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200627 return val;
628}
629
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200630int
631is_restart_error(struct tcb *tcp)
632{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200633 switch (tcp->u_error) {
634 case ERESTARTSYS:
635 case ERESTARTNOINTR:
636 case ERESTARTNOHAND:
637 case ERESTART_RESTARTBLOCK:
638 return 1;
639 default:
640 break;
641 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200642 return 0;
643}
644
Denys Vlasenko523635f2012-02-25 02:44:25 +0100645#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100646struct pt_regs i386_regs;
H.J. Lu35be5812012-04-16 13:00:01 +0200647#elif defined(X86_64) || defined(X32)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100648/*
649 * On 32 bits, pt_regs and user_regs_struct are the same,
650 * but on 64 bits, user_regs_struct has six more fields:
651 * fs_base, gs_base, ds, es, fs, gs.
652 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
653 */
654static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100655#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200656long r8, r10, psr; /* TODO: make static? */
657long ia32 = 0; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100658#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +0100659static long ppc_result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100660#elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200661static long d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100662#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200663static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100664#elif defined(ARM)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200665static struct pt_regs regs;
Steve McIntyred8d3bd32012-10-24 17:58:16 +0100666#elif defined(AARCH64)
667static struct user_pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100668#elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200669static long r0;
670static long a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100671#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200672static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100673#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200674static struct pt_regs regs;
675static unsigned long trap;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100676#elif defined(LINUX_MIPSN32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200677static long long a3;
678static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100679#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200680static long a3;
681static long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100682#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200683static long gpr2;
684static long pc;
685static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100686#elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200687static long r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100688#elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200689static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100690#elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200691static long r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100692#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200693static long r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100694#elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200695static long r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100696#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000697
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200698/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100699 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
700 * 1: ok, continue in trace_syscall_entering().
701 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200702 * ("????" etc) and bail out.
703 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100704static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200705get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000706{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000707 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000708
Denys Vlasenko523635f2012-02-25 02:44:25 +0100709#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000710 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200711 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000712
713 if (syscall_mode != -ENOSYS) {
714 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000715 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000716 */
717 scno = syscall_mode;
718 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000719 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000720 * Old style of "passing" the scno via the SVC instruction.
721 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000722 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200723 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200724 static const int gpr_offset[16] = {
725 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
726 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
727 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
728 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
729 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000730
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000731 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000732 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000733 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000734 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000735 if (errno) {
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000736 perror_msg("%s", "peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000737 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000738 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000739
740 /*
741 * We have to check if the SVC got executed directly or via an
742 * EXECUTE instruction. In case of EXECUTE it is necessary to do
743 * instruction decoding to derive the system call number.
744 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
745 * so that this doesn't work if a SVC opcode is part of an EXECUTE
746 * opcode. Since there is no way to find out the opcode size this
747 * is the best we can do...
748 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000749 if ((opcode & 0xff00) == 0x0a00) {
750 /* SVC opcode */
751 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000752 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000753 else {
754 /* SVC got executed by EXECUTE instruction */
755
756 /*
757 * Do instruction decoding of EXECUTE. If you really want to
758 * understand this, read the Principles of Operations.
759 */
760 svc_addr = (void *) (opcode & 0xfff);
761
762 tmp = 0;
763 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000764 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000765 return -1;
766 svc_addr += tmp;
767
768 tmp = 0;
769 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000770 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000771 return -1;
772 svc_addr += tmp;
773
Denys Vlasenkofb036672009-01-23 16:30:26 +0000774 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000775 if (errno)
776 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100777# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000778 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100779# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000780 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100781# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000782 tmp = 0;
783 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000784 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000785 return -1;
786
787 scno = (scno | tmp) & 0xff;
788 }
789 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100790#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000791 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000792 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100793# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200794 /* TODO: speed up strace by not doing this at every syscall.
795 * We only need to do it after execve.
796 */
797 int currpers;
798 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200799
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200800 /* Check for 64/32 bit mode. */
801 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
802 return -1;
803 /* SF is bit 0 of MSR */
804 if (val < 0)
805 currpers = 0;
806 else
807 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000808 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100809# endif
810#elif defined(AVR32)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200811 /* Read complete register set in one go. */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000812 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
813 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200814 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100815#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000816 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000817 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100818#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200819 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000820 return -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200821 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +0200822#elif defined(X86_64) || defined(X32)
823# ifndef __X32_SYSCALL_BIT
824# define __X32_SYSCALL_BIT 0x40000000
825# endif
826# ifndef __X32_SYSCALL_MASK
827# define __X32_SYSCALL_MASK __X32_SYSCALL_BIT
828# endif
829
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200830 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200831 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
832 return -1;
833 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +0000834
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200835 /* Check CS register value. On x86-64 linux it is:
836 * 0x33 for long mode (64 bit)
837 * 0x23 for compatibility mode (32 bit)
H.J. Lu35be5812012-04-16 13:00:01 +0200838 * Check DS register value. On x86-64 linux it is:
839 * 0x2b for x32 mode (x86-64 in 32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200840 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200841 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200842 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +0200843 case 0x33:
844 if (x86_64_regs.ds == 0x2b) {
845 currpers = 2;
846 scno &= ~__X32_SYSCALL_MASK;
847 } else
848 currpers = 0;
849 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200850 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200851 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200852 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200853 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200854 currpers = current_personality;
855 break;
856 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100857# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200858 /* This version analyzes the opcode of a syscall instruction.
859 * (int 0x80 on i386 vs. syscall on x86-64)
860 * It works, but is too complicated.
861 */
862 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +0000863
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200864 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +0000865
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200866 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
867 rip -= 2;
868 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +0000869
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200870 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200871 if (errno)
872 fprintf(stderr, "ptrace_peektext failed: %s\n",
873 strerror(errno));
874 switch (call & 0xffff) {
875 /* x86-64: syscall = 0x0f 0x05 */
876 case 0x050f: currpers = 0; break;
877 /* i386: int 0x80 = 0xcd 0x80 */
878 case 0x80cd: currpers = 1; break;
879 default:
880 currpers = current_personality;
881 fprintf(stderr,
882 "Unknown syscall opcode (0x%04X) while "
883 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200884 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200885 break;
886 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100887# endif
H.J. Lu35be5812012-04-16 13:00:01 +0200888# ifdef X32
H.J. Lu085e4282012-04-17 11:05:04 -0700889 /* Value of currpers:
890 * 0: 64 bit
891 * 1: 32 bit
892 * 2: X32
893 * Value of current_personality:
894 * 0: X32
895 * 1: 32 bit
896 */
897 switch (currpers) {
898 case 0:
899 fprintf(stderr, "syscall_%lu (...) in unsupported "
900 "64-bit mode of process PID=%d\n",
901 scno, tcp->pid);
902 return 0;
903 case 2:
904 currpers = 0;
H.J. Lu35be5812012-04-16 13:00:01 +0200905 }
H.J. Lu35be5812012-04-16 13:00:01 +0200906# endif
H.J. Lu085e4282012-04-17 11:05:04 -0700907 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100908#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000909# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200910 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000911 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200912 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200913 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200914 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000915 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200916 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000917 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200918 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100919#elif defined(ARM)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200920 /* Read complete register set in one go. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000921 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +0000922 return -1;
923
924 /*
925 * We only need to grab the syscall number on syscall entry.
926 */
927 if (regs.ARM_ip == 0) {
928 /*
929 * Note: we only deal with only 32-bit CPUs here.
930 */
931 if (regs.ARM_cpsr & 0x20) {
932 /*
933 * Get the Thumb-mode system call number
934 */
935 scno = regs.ARM_r7;
936 } else {
937 /*
938 * Get the ARM-mode system call number
939 */
940 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000941 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +0000942 if (errno)
943 return -1;
944
Roland McGrathf691bd22006-04-25 07:34:41 +0000945 /* Handle the EABI syscall convention. We do not
946 bother converting structures between the two
947 ABIs, but basic functionality should work even
948 if strace and the traced program have different
949 ABIs. */
950 if (scno == 0xef000000) {
951 scno = regs.ARM_r7;
952 } else {
953 if ((scno & 0x0ff00000) != 0x0f900000) {
954 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
955 scno);
956 return -1;
957 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000958
Roland McGrathf691bd22006-04-25 07:34:41 +0000959 /*
960 * Fixup the syscall number
961 */
962 scno &= 0x000fffff;
963 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000964 }
Roland McGrath56703312008-05-20 01:35:55 +0000965 if (scno & 0x0f0000) {
966 /*
967 * Handle ARM specific syscall
968 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000969 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +0000970 scno &= 0x0000ffff;
971 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000972 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +0000973
Roland McGrath0f87c492003-06-03 23:29:04 +0000974 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200975 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
976 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000977 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +0100978#elif defined(AARCH64)
979 struct iovec io;
980 io.iov_base = &regs;
981 io.iov_len = sizeof(regs);
982 if (ptrace(PTRACE_GETREGSET, tcp->pid, NT_PRSTATUS, (void *)&io) == -1)
983 return -1;
984 scno = regs.regs[8];
Denys Vlasenko523635f2012-02-25 02:44:25 +0100985#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000986 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000987 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100988#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +0000989 unsigned long long regs[38];
990
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200991 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +0000992 return -1;
993 a3 = regs[REG_A3];
994 r2 = regs[REG_V0];
995
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200996 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200997 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200998 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100999 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001000 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001001 return 0;
1002 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001003 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001004#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001005 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001006 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001007 if (upeek(tcp, REG_V0, &scno) < 0)
1008 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001009
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001010 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001011 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001012 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001013 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001014 return 0;
1015 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001016 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001017#elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001018 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001019 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001020 if (upeek(tcp, REG_R0, &scno) < 0)
1021 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001022
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001023 /*
1024 * Do some sanity checks to figure out if it's
1025 * really a syscall entry
1026 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001027 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001028 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001029 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001030 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001031 return 0;
1032 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001033 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001034#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001035 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001036 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001037 return -1;
1038
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001039 /* Disassemble the syscall trap. */
1040 /* Retrieve the syscall trap instruction. */
1041 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001042# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001043 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1044 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001045# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001046 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001047# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001048 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001049 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001050
1051 /* Disassemble the trap to see what personality to use. */
1052 switch (trap) {
1053 case 0x91d02010:
1054 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001055 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001056 break;
1057 case 0x91d0206d:
1058 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001059 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001060 break;
1061 case 0x91d02000:
1062 /* SunOS syscall trap. (pers 1) */
1063 fprintf(stderr, "syscall: SunOS no support\n");
1064 return -1;
1065 case 0x91d02008:
1066 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001067 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001068 break;
1069 case 0x91d02009:
1070 /* NetBSD/FreeBSD syscall trap. */
1071 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1072 return -1;
1073 case 0x91d02027:
1074 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001075 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001076 break;
1077 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001078# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001079 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001080# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001081 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001082# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001083 return -1;
1084 }
1085
1086 /* Extract the system call number from the registers. */
1087 if (trap == 0x91d02027)
1088 scno = 156;
1089 else
1090 scno = regs.u_regs[U_REG_G1];
1091 if (scno == 0) {
1092 scno = regs.u_regs[U_REG_O0];
1093 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1094 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001095#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001096 if (upeek(tcp, PT_GR20, &scno) < 0)
1097 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001098#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001099 /*
1100 * In the new syscall ABI, the system call number is in R3.
1101 */
1102 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1103 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001104
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001105 if (scno < 0) {
1106 /* Odd as it may seem, a glibc bug has been known to cause
1107 glibc to issue bogus negative syscall numbers. So for
1108 our purposes, make strace print what it *should* have been */
1109 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001110 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001111 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001112 "Detected glibc bug: bogus system call"
1113 " number = %ld, correcting to %ld\n",
1114 scno,
1115 correct_scno);
1116 scno = correct_scno;
1117 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001118#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001119 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001120 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001121 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001122#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001123 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1124 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001125#elif defined(TILE)
Chris Metcalfc8c66982009-12-28 10:00:15 -05001126 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1127 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001128#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001129 if (upeek(tcp, 0, &scno) < 0)
1130 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001131#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001132
Denys Vlasenko523635f2012-02-25 02:44:25 +01001133#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001134 /* new syscall ABI returns result in R0 */
1135 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1136 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001137#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001138 /* ABI defines result returned in r9 */
1139 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1140 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001141#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001142
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001143 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001144 return 1;
1145}
1146
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001147/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001148 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001149 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1150 * 1: ok, continue in trace_syscall_entering().
1151 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001152 * ("????" etc) and bail out.
1153 */
Roland McGratha4d48532005-06-08 20:45:28 +00001154static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001155syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001156{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001157 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001158#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001159 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001160 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001161 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1162 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163 }
H.J. Lu35be5812012-04-16 13:00:01 +02001164#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001165 {
1166 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001167 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001168 rax = (int)rax; /* sign extend from 32 bits */
1169 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001170 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001171 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1172 return 0;
1173 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001174 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001175#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001176 /* TODO: we already fetched PT_GPR2 in get_scno
1177 * and stored it in syscall_mode, reuse it here
1178 * instead of re-fetching?
1179 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001180 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001181 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001182 if (syscall_mode != -ENOSYS)
1183 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001184 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001185 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001186 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001187 return 0;
1188 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001189#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001190 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001191 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001192 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001193 if (d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001194 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001195 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001196 return 0;
1197 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001198#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001199 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001200 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001201 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001202 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001203 if (ia32 && r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001204 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001205 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001206 return 0;
1207 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001208#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001209 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001210 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001211 if (r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001212 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001213 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001214 return 0;
1215 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001216#elif defined(MICROBLAZE)
1217 if (upeek(tcp, 3 * 4, &r3) < 0)
1218 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001219 if (r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001220 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001221 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001222 return 0;
1223 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001224#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001225 return 1;
1226}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001227
Denys Vlasenko146b9442012-03-18 22:10:48 +01001228static void
1229internal_fork(struct tcb *tcp)
1230{
1231#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1232# define ARG_FLAGS 1
1233#else
1234# define ARG_FLAGS 0
1235#endif
1236#ifndef CLONE_UNTRACED
1237# define CLONE_UNTRACED 0x00800000
1238#endif
1239 if ((ptrace_setoptions
1240 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1241 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1242 return;
1243
1244 if (!followfork)
1245 return;
1246
1247 if (entering(tcp)) {
1248 /*
1249 * We won't see the new child if clone is called with
1250 * CLONE_UNTRACED, so we keep the same logic with that option
1251 * and don't trace it.
1252 */
1253 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1254 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1255 return;
1256 setbpt(tcp);
1257 } else {
1258 if (tcp->flags & TCB_BPTSET)
1259 clearbpt(tcp);
1260 }
1261}
1262
1263#if defined(TCB_WAITEXECVE)
1264static void
1265internal_exec(struct tcb *tcp)
1266{
1267 /* Maybe we have post-execve SIGTRAP suppressed? */
1268 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1269 return; /* yes, no need to do anything */
1270
1271 if (exiting(tcp) && syserror(tcp))
1272 /* Error in execve, no post-execve SIGTRAP expected */
1273 tcp->flags &= ~TCB_WAITEXECVE;
1274 else
1275 tcp->flags |= TCB_WAITEXECVE;
1276}
1277#endif
1278
1279static void
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001280internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001281{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001282 /*
1283 * We must always trace a few critical system calls in order to
1284 * correctly support following forks in the presence of tracing
1285 * qualifiers.
1286 */
1287 int (*func)();
1288
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001289 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001290 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001291
1292 func = sysent[tcp->scno].sys_func;
1293
1294 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001295 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001296 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001297 ) {
1298 internal_fork(tcp);
1299 return;
1300 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001301
Denys Vlasenko84703742012-02-25 02:38:52 +01001302#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001303 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001304# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001305 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001306# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001307 ) {
1308 internal_exec(tcp);
1309 return;
1310 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001311#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001312}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001313
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001314/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001315static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001316get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001317{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001318 int i, nargs;
1319
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001320 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001321 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001322 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001323 nargs = tcp->u_nargs = MAX_ARGS;
1324
Denys Vlasenko523635f2012-02-25 02:44:25 +01001325#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001326 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001327 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1328 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001329#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001330 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001331 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1332 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001333#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001334 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001335 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001336 long rbs_end;
1337 /* be backwards compatible with kernel < 2.4.4... */
1338# ifndef PT_RBS_END
1339# define PT_RBS_END PT_AR_BSP
1340# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001341
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001342 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1343 return -1;
1344 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001345 return -1;
1346
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001347 sof = (cfm >> 0) & 0x7f;
1348 sol = (cfm >> 7) & 0x7f;
1349 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1350
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001351 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001352 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1353 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1354 return -1;
1355 }
1356 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001357 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1358 PT_R9 /* ECX = out1 */,
1359 PT_R10 /* EDX = out2 */,
1360 PT_R14 /* ESI = out3 */,
1361 PT_R15 /* EDI = out4 */,
1362 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001363
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001364 for (i = 0; i < nargs; ++i) {
1365 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1366 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001367 /* truncate away IVE sign-extension */
1368 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001369 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001370 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001371#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001372 /* N32 and N64 both use up to six registers. */
1373 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001374
1375 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1376 return -1;
1377
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001378 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001379 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001380# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001381 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001382# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001383 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001384#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001385 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001386 long sp;
1387
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001388 if (upeek(tcp, REG_SP, &sp) < 0)
1389 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001390 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001391 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1392 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001393 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001394 (char *)(tcp->u_arg + 4));
1395 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001396 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001397 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001398 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001399 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001400#elif defined(POWERPC)
1401# ifndef PT_ORIG_R3
1402# define PT_ORIG_R3 34
1403# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001404 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001405 if (upeek(tcp, (i==0) ?
1406 (sizeof(unsigned long) * PT_ORIG_R3) :
1407 ((i+PT_R3) * sizeof(unsigned long)),
1408 &tcp->u_arg[i]) < 0)
1409 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001410 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001411#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001412 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001413 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001414#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001415 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001416 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1417 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001418#elif defined(ARM)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001419 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001420 tcp->u_arg[i] = regs.uregs[i];
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001421#elif defined(AARCH64)
1422 for (i = 0; i < nargs; ++i)
1423 tcp->u_arg[i] = regs.regs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001424#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001425 (void)i;
1426 (void)nargs;
1427 tcp->u_arg[0] = regs.r12;
1428 tcp->u_arg[1] = regs.r11;
1429 tcp->u_arg[2] = regs.r10;
1430 tcp->u_arg[3] = regs.r9;
1431 tcp->u_arg[4] = regs.r5;
1432 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001433#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001434 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 +02001435
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001436 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001437 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1438 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001439#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001440 static const int syscall_regs[MAX_ARGS] = {
1441 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1442 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001443 };
1444
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001445 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001446 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001447 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001448#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001449 int i;
1450 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001451 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001452
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001453 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001454 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1455 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001456#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001457 (void)i;
1458 (void)nargs;
H.J. Lu35be5812012-04-16 13:00:01 +02001459 if (current_personality != 1) { /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001460 tcp->u_arg[0] = x86_64_regs.rdi;
1461 tcp->u_arg[1] = x86_64_regs.rsi;
1462 tcp->u_arg[2] = x86_64_regs.rdx;
1463 tcp->u_arg[3] = x86_64_regs.r10;
1464 tcp->u_arg[4] = x86_64_regs.r8;
1465 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001466# ifdef X32
1467 tcp->ext_arg[0] = x86_64_regs.rdi;
1468 tcp->ext_arg[1] = x86_64_regs.rsi;
1469 tcp->ext_arg[2] = x86_64_regs.rdx;
1470 tcp->ext_arg[3] = x86_64_regs.r10;
1471 tcp->ext_arg[4] = x86_64_regs.r8;
1472 tcp->ext_arg[5] = x86_64_regs.r9;
1473# endif
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001474 } else { /* i386 ABI */
1475 /* Sign-extend lower 32 bits */
1476 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1477 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1478 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1479 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1480 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1481 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1482 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001483#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001484 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001485 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1486 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001487#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001488 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001489 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001490 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001491 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001492
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001493 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001494 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1495 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001496#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001497 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001498 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1499 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001500#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001501 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001502 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1503 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001504#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001505 (void)i;
1506 (void)nargs;
1507 tcp->u_arg[0] = i386_regs.ebx;
1508 tcp->u_arg[1] = i386_regs.ecx;
1509 tcp->u_arg[2] = i386_regs.edx;
1510 tcp->u_arg[3] = i386_regs.esi;
1511 tcp->u_arg[4] = i386_regs.edi;
1512 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001513#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001514 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001515 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1516 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001517#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001518 return 1;
1519}
1520
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001521static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001522trace_syscall_entering(struct tcb *tcp)
1523{
1524 int res, scno_good;
1525
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001526#if defined TCB_WAITEXECVE
1527 if (tcp->flags & TCB_WAITEXECVE) {
1528 /* This is the post-execve SIGTRAP. */
1529 tcp->flags &= ~TCB_WAITEXECVE;
1530 return 0;
1531 }
1532#endif
1533
Denys Vlasenko06602d92011-08-24 17:53:52 +02001534 scno_good = res = get_scno(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001535 if (res == 0)
1536 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001537 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001538 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001539 if (res == 0)
1540 return res;
1541 if (res == 1)
1542 res = get_syscall_args(tcp);
1543 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001544
1545 if (res != 1) {
1546 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001547 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001548 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001549 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001550 tprintf("syscall_%lu(", tcp->scno);
1551 else
1552 tprintf("%s(", sysent[tcp->scno].sys_name);
1553 /*
1554 * " <unavailable>" will be added later by the code which
1555 * detects ptrace errors.
1556 */
1557 goto ret;
1558 }
1559
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001560#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1561 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001562# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001563 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001564 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001565 break;
1566 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001567# endif
1568# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001569 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001570 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001571 break;
1572 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001573# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001574 break;
1575 }
1576#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1577
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001578 internal_syscall(tcp);
1579
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001580 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001581 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1582 (tracing_paths && !pathtrace_match(tcp))) {
1583 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1584 return 0;
1585 }
1586
1587 tcp->flags &= ~TCB_FILTERED;
1588
1589 if (cflag == CFLAG_ONLY_STATS) {
1590 res = 0;
1591 goto ret;
1592 }
1593
1594 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001595 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001596 tprintf("syscall_%lu(", tcp->scno);
1597 else
1598 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001599 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001600 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1601 sysent[tcp->scno].sys_func != sys_exit))
1602 res = printargs(tcp);
1603 else
1604 res = (*sysent[tcp->scno].sys_func)(tcp);
1605
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001606 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001607 ret:
1608 tcp->flags |= TCB_INSYSCALL;
1609 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001610 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001611 gettimeofday(&tcp->etime, NULL);
1612 return res;
1613}
1614
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001615/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001616 * 1: ok, continue in trace_syscall_exiting().
1617 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001618 * ("????" etc) and bail out.
1619 */
1620static int
1621get_syscall_result(struct tcb *tcp)
1622{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001623#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001624 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1625 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001626#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001627# define SO_MASK 0x10000000
1628 {
1629 long flags;
1630 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1631 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001632 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001633 return -1;
1634 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001635 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001636 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001637#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001638 /* Read complete register set in one go. */
1639 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1640 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001641#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001642 if (upeek(tcp, PT_R0, &r0) < 0)
1643 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001644#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001645 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001646 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001647#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001648 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001649 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001650#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001651# define IA64_PSR_IS ((long)1 << 34)
1652 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1653 ia32 = (psr & IA64_PSR_IS) != 0;
1654 if (upeek(tcp, PT_R8, &r8) < 0)
1655 return -1;
1656 if (upeek(tcp, PT_R10, &r10) < 0)
1657 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001658#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001659 /* Read complete register set in one go. */
1660 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1661 return -1;
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001662#elif defined(AARCH64)
1663 struct iovec io;
1664 io.iov_base = &regs;
1665 io.iov_len = sizeof(regs);
1666 if (ptrace(PTRACE_GETREGSET, tcp->pid, NT_PRSTATUS, (void *)&io) == -1)
1667 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001668#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001669 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1670 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001671#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001672 unsigned long long regs[38];
1673
1674 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1675 return -1;
1676 a3 = regs[REG_A3];
1677 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001678#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001679 if (upeek(tcp, REG_A3, &a3) < 0)
1680 return -1;
1681 if (upeek(tcp, REG_V0, &r2) < 0)
1682 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001683#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001684 if (upeek(tcp, REG_A3, &a3) < 0)
1685 return -1;
1686 if (upeek(tcp, REG_R0, &r0) < 0)
1687 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001688#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001689 /* Everything we need is in the current register set. */
1690 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1691 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001692#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001693 if (upeek(tcp, PT_GR28, &r28) < 0)
1694 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001695#elif defined(SH)
1696#elif defined(SH64)
1697#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001698 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1699 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001700#elif defined(TILE)
1701#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001702 if (upeek(tcp, 3 * 4, &r3) < 0)
1703 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001704#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001705
Denys Vlasenko523635f2012-02-25 02:44:25 +01001706#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001707 /* new syscall ABI returns result in R0 */
1708 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1709 return -1;
1710#elif defined(SH64)
1711 /* ABI defines result returned in r9 */
1712 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1713 return -1;
1714#endif
1715
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001716 return 1;
1717}
1718
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001719/* Called at each syscall exit */
1720static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001721syscall_fixup_on_sysexit(struct tcb *tcp)
1722{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001723#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001724 if (syscall_mode != -ENOSYS)
1725 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001726 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001727 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1728 /*
1729 * Return from execve.
1730 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1731 * flag set for the post-execve SIGTRAP to see and reset.
1732 */
1733 gpr2 = 0;
1734 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001735#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001736}
1737
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001738/*
1739 * Check the syscall return value register value for whether it is
1740 * a negated errno code indicating an error, or a success return value.
1741 */
1742static inline int
1743is_negated_errno(unsigned long int val)
1744{
1745 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001746#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001747 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001748 val = (unsigned int) val;
1749 max = (unsigned int) max;
1750 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001751#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001752 return val > max;
1753}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001754
Denys Vlasenko907735a2012-03-21 00:23:16 +01001755/* Returns:
1756 * 1: ok, continue in trace_syscall_exiting().
1757 * -1: error, trace_syscall_exiting() should print error indicator
1758 * ("????" etc) and bail out.
1759 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001760static int
1761get_error(struct tcb *tcp)
1762{
1763 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001764 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001765 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001766 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1767 check_errno = 0;
1768 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001769#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001770 if (check_errno && is_negated_errno(gpr2)) {
1771 tcp->u_rval = -1;
1772 u_error = -gpr2;
1773 }
1774 else {
1775 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001776 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001777#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001778 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001779 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001780 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001781 }
1782 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001783 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001784 }
H.J. Lu35be5812012-04-16 13:00:01 +02001785#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001786 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001787 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001788 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001789 }
1790 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001791 tcp->u_rval = x86_64_regs.rax;
H.J. Lu35be5812012-04-16 13:00:01 +02001792# if defined(X32)
1793 tcp->u_lrval = x86_64_regs.rax;
1794# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001795 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001796#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001797 if (ia32) {
1798 int err;
1799
1800 err = (int)r8;
1801 if (check_errno && is_negated_errno(err)) {
1802 tcp->u_rval = -1;
1803 u_error = -err;
1804 }
1805 else {
1806 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001807 }
1808 } else {
1809 if (check_errno && r10) {
1810 tcp->u_rval = -1;
1811 u_error = r8;
1812 } else {
1813 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001814 }
1815 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001816#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001817 if (check_errno && a3) {
1818 tcp->u_rval = -1;
1819 u_error = r2;
1820 } else {
1821 tcp->u_rval = r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02001822# if defined(LINUX_MIPSN32)
1823 tcp->u_lrval = r2;
1824# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001825 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001826#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001827 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001828 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001829 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001830 }
1831 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001832 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001833 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001834#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001835 if (check_errno && is_negated_errno(d0)) {
1836 tcp->u_rval = -1;
1837 u_error = -d0;
1838 }
1839 else {
1840 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001841 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001842#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001843 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1844 tcp->u_rval = -1;
1845 u_error = -regs.ARM_r0;
1846 }
1847 else {
1848 tcp->u_rval = regs.ARM_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001849 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001850#elif defined(AARCH64)
1851 if (check_errno && is_negated_errno(regs.regs[0])) {
1852 tcp->u_rval = -1;
1853 u_error = -regs.regs[0];
1854 }
1855 else {
1856 tcp->u_rval = regs.regs[0];
1857 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001858#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001859 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1860 tcp->u_rval = -1;
1861 u_error = -regs.r12;
1862 }
1863 else {
1864 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001865 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001866#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001867 if (check_errno && is_negated_errno(r0)) {
1868 tcp->u_rval = -1;
1869 u_error = -r0;
1870 } else {
1871 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001872 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001873#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001874 if (check_errno && a3) {
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(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001882 if (check_errno && regs.psr & PSR_C) {
1883 tcp->u_rval = -1;
1884 u_error = regs.u_regs[U_REG_O0];
1885 }
1886 else {
1887 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001888 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001889#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001890 if (check_errno && regs.tstate & 0x1100000000UL) {
1891 tcp->u_rval = -1;
1892 u_error = regs.u_regs[U_REG_O0];
1893 }
1894 else {
1895 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001896 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001897#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001898 if (check_errno && is_negated_errno(r28)) {
1899 tcp->u_rval = -1;
1900 u_error = -r28;
1901 }
1902 else {
1903 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001904 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001905#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001906 if (check_errno && is_negated_errno(r0)) {
1907 tcp->u_rval = -1;
1908 u_error = -r0;
1909 }
1910 else {
1911 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001912 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001913#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001914 if (check_errno && is_negated_errno(r9)) {
1915 tcp->u_rval = -1;
1916 u_error = -r9;
1917 }
1918 else {
1919 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001920 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001921#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001922 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1923 tcp->u_rval = -1;
1924 u_error = -r10;
1925 }
1926 else {
1927 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001928 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001929#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001930 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001931 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1932 return -1;
1933 if (check_errno && rval < 0 && rval > -nerrnos) {
1934 tcp->u_rval = -1;
1935 u_error = -rval;
1936 }
1937 else {
1938 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001939 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001940#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001941 if (check_errno && is_negated_errno(r3)) {
1942 tcp->u_rval = -1;
1943 u_error = -r3;
1944 }
1945 else {
1946 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001947 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001948#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001949 tcp->u_error = u_error;
1950 return 1;
1951}
1952
1953static void
1954dumpio(struct tcb *tcp)
1955{
1956 if (syserror(tcp))
1957 return;
1958 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1959 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001960 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001961 return;
1962 if (sysent[tcp->scno].sys_func == printargs)
1963 return;
1964 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1965 if (sysent[tcp->scno].sys_func == sys_read ||
1966 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001967 sysent[tcp->scno].sys_func == sys_recv ||
1968 sysent[tcp->scno].sys_func == sys_recvfrom)
1969 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1970 else if (sysent[tcp->scno].sys_func == sys_readv)
1971 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1972 return;
1973 }
1974 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1975 if (sysent[tcp->scno].sys_func == sys_write ||
1976 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001977 sysent[tcp->scno].sys_func == sys_send ||
1978 sysent[tcp->scno].sys_func == sys_sendto)
1979 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1980 else if (sysent[tcp->scno].sys_func == sys_writev)
1981 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1982 return;
1983 }
1984}
1985
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001986static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001987trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001988{
1989 int sys_res;
1990 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001991 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001992 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001993
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001994 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001995 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001996 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001997
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001998#if SUPPORTED_PERSONALITIES > 1
1999 update_personality(tcp, tcp->currpers);
2000#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002001 res = get_syscall_result(tcp);
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002002 if (res == 1) {
2003 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01002004 res = get_error(tcp); /* returns 1 or -1 */
2005 if (res == 1) {
2006 internal_syscall(tcp);
2007 if (filtered(tcp)) {
2008 goto ret;
2009 }
2010 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002011 }
2012
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002013 if (cflag) {
2014 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002015 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002016 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002017 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002018 }
2019 }
2020
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002021 /* If not in -ff mode, and printing_tcp != tcp,
2022 * then the log currently does not end with output
2023 * of _our syscall entry_, but with something else.
2024 * We need to say which syscall's return is this.
2025 *
2026 * Forced reprinting via TCB_REPRINT is used only by
2027 * "strace -ff -oLOG test/threaded_execve" corner case.
2028 * It's the only case when -ff mode needs reprinting.
2029 */
2030 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2031 tcp->flags &= ~TCB_REPRINT;
2032 printleader(tcp);
2033 if (!SCNO_IN_RANGE(tcp->scno))
2034 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2035 else
2036 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2037 }
2038 printing_tcp = tcp;
2039
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002040 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002041 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002042 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002043 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002044 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002045 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002046 tcp->flags &= ~TCB_INSYSCALL;
2047 return res;
2048 }
2049
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002050 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002051 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002052 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002053 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002054 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002055 /* FIXME: not_failing_only (IOW, option -z) is broken:
2056 * failure of syscall is known only after syscall return.
2057 * Thus we end up with something like this on, say, ENOENT:
2058 * open("doesnt_exist", O_RDONLY <unfinished ...>
2059 * {next syscall decode}
2060 * whereas the intended result is that open(...) line
2061 * is not shown at all.
2062 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002063 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002064 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002065 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2066 }
2067
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002068 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002069 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002070 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002071 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002072 qual_flags[tcp->scno] & QUAL_RAW) {
2073 if (u_error)
2074 tprintf("= -1 (errno %ld)", u_error);
2075 else
2076 tprintf("= %#lx", tcp->u_rval);
2077 }
2078 else if (!(sys_res & RVAL_NONE) && u_error) {
2079 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002080 /* Blocked signals do not interrupt any syscalls.
2081 * In this case syscalls don't return ERESTARTfoo codes.
2082 *
2083 * Deadly signals set to SIG_DFL interrupt syscalls
2084 * and kill the process regardless of which of the codes below
2085 * is returned by the interrupted syscall.
2086 * In some cases, kernel forces a kernel-generated deadly
2087 * signal to be unblocked and set to SIG_DFL (and thus cause
2088 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2089 * or SIGILL. (The alternative is to leave process spinning
2090 * forever on the faulty instruction - not useful).
2091 *
2092 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2093 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2094 * but kernel will always restart them.
2095 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002096 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002097 /* Most common type of signal-interrupted syscall exit code.
2098 * The system call will be restarted with the same arguments
2099 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2100 */
2101 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002102 break;
2103 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002104 /* Rare. For example, fork() returns this if interrupted.
2105 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2106 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002107 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002108 break;
2109 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002110 /* pause(), rt_sigsuspend() etc use this code.
2111 * SA_RESTART is ignored (assumed not set):
2112 * syscall won't restart (will return EINTR instead)
2113 * even after signal with SA_RESTART set.
2114 * However, after SIG_IGN or SIG_DFL signal it will.
2115 */
2116 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002117 break;
2118 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002119 /* Syscalls like nanosleep(), poll() which can't be
2120 * restarted with their original arguments use this
2121 * code. Kernel will execute restart_syscall() instead,
2122 * which changes arguments before restarting syscall.
2123 * SA_RESTART is ignored (assumed not set) similarly
2124 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2125 * since restart data is saved in "restart block"
2126 * in task struct, and if signal handler uses a syscall
2127 * which in turn saves another such restart block,
2128 * old data is lost and restart becomes impossible)
2129 */
2130 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002131 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002132 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002133 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002134 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002135 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002136 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002137 strerror(u_error));
2138 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002139 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002140 strerror(u_error));
2141 break;
2142 }
2143 if ((sys_res & RVAL_STR) && tcp->auxstr)
2144 tprintf(" (%s)", tcp->auxstr);
2145 }
2146 else {
2147 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002148 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002149 else {
2150 switch (sys_res & RVAL_MASK) {
2151 case RVAL_HEX:
2152 tprintf("= %#lx", tcp->u_rval);
2153 break;
2154 case RVAL_OCTAL:
2155 tprintf("= %#lo", tcp->u_rval);
2156 break;
2157 case RVAL_UDECIMAL:
2158 tprintf("= %lu", tcp->u_rval);
2159 break;
2160 case RVAL_DECIMAL:
2161 tprintf("= %ld", tcp->u_rval);
2162 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002163#if defined(LINUX_MIPSN32) || defined(X32)
2164 /*
2165 case RVAL_LHEX:
2166 tprintf("= %#llx", tcp->u_lrval);
2167 break;
2168 case RVAL_LOCTAL:
2169 tprintf("= %#llo", tcp->u_lrval);
2170 break;
2171 */
2172 case RVAL_LUDECIMAL:
2173 tprintf("= %llu", tcp->u_lrval);
2174 break;
2175 /*
2176 case RVAL_LDECIMAL:
2177 tprintf("= %lld", tcp->u_lrval);
2178 break;
2179 */
2180#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002181 default:
2182 fprintf(stderr,
2183 "invalid rval format\n");
2184 break;
2185 }
2186 }
2187 if ((sys_res & RVAL_STR) && tcp->auxstr)
2188 tprintf(" (%s)", tcp->auxstr);
2189 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002190 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002191 tv_sub(&tv, &tv, &tcp->etime);
2192 tprintf(" <%ld.%06ld>",
2193 (long) tv.tv_sec, (long) tv.tv_usec);
2194 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002195 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002196 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002197 line_ended();
2198
Denys Vlasenko3b738812011-08-22 02:06:35 +02002199 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002200 tcp->flags &= ~TCB_INSYSCALL;
2201 return 0;
2202}
2203
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002204int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002205trace_syscall(struct tcb *tcp)
2206{
2207 return exiting(tcp) ?
2208 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2209}