blob: 69eceed5fffec4b0694a2fdea6a92d75e963ed71 [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 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000290# elif defined(AARCH64)
291 if (!qflag) {
292 static const char *const names[] = {"32-bit ARM", "AArch64"};
293 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
294 tcp->pid, names[personality]);
295 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100296# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000297}
298#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000299
Roland McGrath9797ceb2002-12-30 10:23:00 +0000300static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000301
Roland McGrathe10e62a2004-09-04 04:20:43 +0000302static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000303 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000304 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000305 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000306 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000307} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000308 { QUAL_TRACE, "trace", qual_syscall, "system call" },
309 { QUAL_TRACE, "t", qual_syscall, "system call" },
310 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
311 { QUAL_ABBREV, "a", qual_syscall, "system call" },
312 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
313 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
314 { QUAL_RAW, "raw", qual_syscall, "system call" },
315 { QUAL_RAW, "x", qual_syscall, "system call" },
316 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
317 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
318 { QUAL_SIGNAL, "s", qual_signal, "signal" },
319 { QUAL_FAULT, "fault", qual_fault, "fault" },
320 { QUAL_FAULT, "faults", qual_fault, "fault" },
321 { QUAL_FAULT, "m", qual_fault, "fault" },
322 { QUAL_READ, "read", qual_desc, "descriptor" },
323 { QUAL_READ, "reads", qual_desc, "descriptor" },
324 { QUAL_READ, "r", qual_desc, "descriptor" },
325 { QUAL_WRITE, "write", qual_desc, "descriptor" },
326 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
327 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000328 { 0, NULL, NULL, NULL },
329};
330
Roland McGrath9797ceb2002-12-30 10:23:00 +0000331static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000332qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000333{
Roland McGrath138c6a32006-01-12 09:50:49 +0000334 if (pers == 0 || pers < 0) {
335 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000336 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000337 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000338 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000339 }
340
341#if SUPPORTED_PERSONALITIES >= 2
342 if (pers == 1 || pers < 0) {
343 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000344 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000345 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000346 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000347 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100348#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000349
350#if SUPPORTED_PERSONALITIES >= 3
351 if (pers == 2 || pers < 0) {
352 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000353 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000354 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000355 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000356 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100357#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000358}
359
360static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000361qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000362{
363 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000364 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000365
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100366 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000367 int i = string_to_uint(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000368 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000369 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000370 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000371 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000372 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000373 for (i = 0; i < nsyscalls0; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000374 if (sysent0[i].sys_name &&
375 strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000376 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000377 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000378 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000379
380#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000381 for (i = 0; i < nsyscalls1; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000382 if (sysent1[i].sys_name &&
383 strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000384 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000385 rc = 0;
386 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100387#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000388
389#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000390 for (i = 0; i < nsyscalls2; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000391 if (sysent2[i].sys_name &&
392 strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000393 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000394 rc = 0;
395 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100396#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000397
Roland McGrathfe6b3522005-02-02 04:40:11 +0000398 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000399}
400
401static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000402qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000403{
404 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000405
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100406 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000407 int signo = string_to_uint(s);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000408 if (signo < 0 || signo >= MAX_QUALS)
409 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000410 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000411 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000412 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000413 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000414 s += 3;
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100415 for (i = 0; i <= NSIG; i++) {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000416 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000417 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000418 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000419 }
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100420 }
Roland McGrath76421df2005-02-02 03:51:18 +0000421 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000422}
423
424static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000425qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000426{
427 return -1;
428}
429
430static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000431qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000432{
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100433 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000434 int desc = string_to_uint(s);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000435 if (desc < 0 || desc >= MAX_QUALS)
436 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000437 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000438 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000439 }
440 return -1;
441}
442
443static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000444lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000445{
446 if (strcmp(s, "file") == 0)
447 return TRACE_FILE;
448 if (strcmp(s, "ipc") == 0)
449 return TRACE_IPC;
450 if (strcmp(s, "network") == 0)
451 return TRACE_NETWORK;
452 if (strcmp(s, "process") == 0)
453 return TRACE_PROCESS;
454 if (strcmp(s, "signal") == 0)
455 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000456 if (strcmp(s, "desc") == 0)
457 return TRACE_DESC;
Namhyung Kim96792962012-10-24 11:41:57 +0900458 if (strcmp(s, "memory") == 0)
459 return TRACE_MEMORY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000460 return -1;
461}
462
463void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000464qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000465{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000466 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000467 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000468 char *copy;
469 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000470 int i, n;
471
472 opt = &qual_options[0];
473 for (i = 0; (p = qual_options[i].option_name); i++) {
474 n = strlen(p);
475 if (strncmp(s, p, n) == 0 && s[n] == '=') {
476 opt = &qual_options[i];
477 s += n + 1;
478 break;
479 }
480 }
481 not = 0;
482 if (*s == '!') {
483 not = 1;
484 s++;
485 }
486 if (strcmp(s, "none") == 0) {
487 not = 1 - not;
488 s = "all";
489 }
490 if (strcmp(s, "all") == 0) {
491 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000492 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000493 }
494 return;
495 }
496 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000497 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000498 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200499 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200500 if (!copy)
501 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000502 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000503 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000504 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000505 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000506 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000507
508#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000509 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000510 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000511 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100512#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000513
514#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000515 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000516 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000517 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100518#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000519
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000520 continue;
521 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000522 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100523 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000524 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000525 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000526 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000527 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000528 return;
529}
530
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000531#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000532static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000533decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000534{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000535 unsigned long addr;
536 unsigned int i, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000537
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000538 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
539 return;
540
541 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
542 addr = tcp->u_arg[1];
543 tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100544 size = current_wordsize;
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000545 for (i = 0; i < tcp->u_nargs; ++i) {
546 if (size == sizeof(int)) {
547 unsigned int arg;
548 if (umove(tcp, addr, &arg) < 0)
549 arg = 0;
550 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000551 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000552 else {
553 unsigned long arg;
554 if (umove(tcp, addr, &arg) < 0)
555 arg = 0;
556 tcp->u_arg[i] = arg;
557 }
558 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000559 }
560}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000561#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400562
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000563#ifdef SYS_ipc_subcall
564static void
565decode_ipc_subcall(struct tcb *tcp)
566{
567 unsigned int i;
568
569 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
570 return;
571
572 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
573 tcp->u_nargs = sysent[tcp->scno].nargs;
574 for (i = 0; i < tcp->u_nargs; i++)
575 tcp->u_arg[i] = tcp->u_arg[i + 1];
576}
577#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000578
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200579int
580printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000581{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200582 if (entering(tcp)) {
583 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000584
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200585 for (i = 0; i < tcp->u_nargs; i++)
586 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
587 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000588 return 0;
589}
590
Denys Vlasenko72879c62012-02-27 14:18:02 +0100591int
592printargs_lu(struct tcb *tcp)
593{
594 if (entering(tcp)) {
595 int i;
596
597 for (i = 0; i < tcp->u_nargs; i++)
598 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
599 }
600 return 0;
601}
602
603int
604printargs_ld(struct tcb *tcp)
605{
606 if (entering(tcp)) {
607 int i;
608
609 for (i = 0; i < tcp->u_nargs; i++)
610 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
611 }
612 return 0;
613}
614
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200615long
616getrval2(struct tcb *tcp)
617{
618 long val = -1;
619
Denys Vlasenko523635f2012-02-25 02:44:25 +0100620#if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200621 struct pt_regs regs;
622 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
623 return -1;
624 val = regs.u_regs[U_REG_O1];
625#elif defined(SH)
626 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
627 return -1;
628#elif defined(IA64)
629 if (upeek(tcp, PT_R9, &val) < 0)
630 return -1;
631#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200632
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200633 return val;
634}
635
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200636int
637is_restart_error(struct tcb *tcp)
638{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200639 switch (tcp->u_error) {
640 case ERESTARTSYS:
641 case ERESTARTNOINTR:
642 case ERESTARTNOHAND:
643 case ERESTART_RESTARTBLOCK:
644 return 1;
645 default:
646 break;
647 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200648 return 0;
649}
650
Denys Vlasenko523635f2012-02-25 02:44:25 +0100651#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100652struct pt_regs i386_regs;
H.J. Lu35be5812012-04-16 13:00:01 +0200653#elif defined(X86_64) || defined(X32)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100654/*
655 * On 32 bits, pt_regs and user_regs_struct are the same,
656 * but on 64 bits, user_regs_struct has six more fields:
657 * fs_base, gs_base, ds, es, fs, gs.
658 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
659 */
660static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100661#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200662long r8, r10, psr; /* TODO: make static? */
663long ia32 = 0; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100664#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +0100665static long ppc_result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100666#elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200667static long d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100668#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200669static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100670#elif defined(ARM)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200671static struct pt_regs regs;
Steve McIntyred8d3bd32012-10-24 17:58:16 +0100672#elif defined(AARCH64)
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000673static struct user_pt_regs aarch64_regs;
674static struct arm_pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100675#elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200676static long r0;
677static long a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100678#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200679static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100680#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200681static struct pt_regs regs;
682static unsigned long trap;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100683#elif defined(LINUX_MIPSN32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200684static long long a3;
685static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100686#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200687static long a3;
688static long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100689#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200690static long gpr2;
691static long pc;
692static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100693#elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200694static long r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100695#elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200696static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100697#elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200698static long r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100699#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200700static long r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100701#elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200702static long r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100703#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000704
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200705/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100706 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
707 * 1: ok, continue in trace_syscall_entering().
708 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200709 * ("????" etc) and bail out.
710 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100711static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200712get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000713{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000714 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000715
Denys Vlasenko523635f2012-02-25 02:44:25 +0100716#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000717 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200718 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000719
720 if (syscall_mode != -ENOSYS) {
721 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000722 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000723 */
724 scno = syscall_mode;
725 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000726 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000727 * Old style of "passing" the scno via the SVC instruction.
728 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000729 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200730 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200731 static const int gpr_offset[16] = {
732 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
733 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
734 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
735 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
736 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000737
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000738 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000739 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000740 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000741 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000742 if (errno) {
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000743 perror_msg("%s", "peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000744 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000745 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000746
747 /*
748 * We have to check if the SVC got executed directly or via an
749 * EXECUTE instruction. In case of EXECUTE it is necessary to do
750 * instruction decoding to derive the system call number.
751 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
752 * so that this doesn't work if a SVC opcode is part of an EXECUTE
753 * opcode. Since there is no way to find out the opcode size this
754 * is the best we can do...
755 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000756 if ((opcode & 0xff00) == 0x0a00) {
757 /* SVC opcode */
758 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000759 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000760 else {
761 /* SVC got executed by EXECUTE instruction */
762
763 /*
764 * Do instruction decoding of EXECUTE. If you really want to
765 * understand this, read the Principles of Operations.
766 */
767 svc_addr = (void *) (opcode & 0xfff);
768
769 tmp = 0;
770 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000771 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000772 return -1;
773 svc_addr += tmp;
774
775 tmp = 0;
776 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000777 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000778 return -1;
779 svc_addr += tmp;
780
Denys Vlasenkofb036672009-01-23 16:30:26 +0000781 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000782 if (errno)
783 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100784# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000785 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100786# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000787 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100788# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000789 tmp = 0;
790 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000791 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000792 return -1;
793
794 scno = (scno | tmp) & 0xff;
795 }
796 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100797#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000798 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000799 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100800# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200801 /* TODO: speed up strace by not doing this at every syscall.
802 * We only need to do it after execve.
803 */
804 int currpers;
805 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200806
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200807 /* Check for 64/32 bit mode. */
808 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
809 return -1;
810 /* SF is bit 0 of MSR */
811 if (val < 0)
812 currpers = 0;
813 else
814 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000815 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100816# endif
817#elif defined(AVR32)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200818 /* Read complete register set in one go. */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000819 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
820 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200821 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100822#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000823 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000824 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100825#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200826 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000827 return -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200828 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +0200829#elif defined(X86_64) || defined(X32)
830# ifndef __X32_SYSCALL_BIT
831# define __X32_SYSCALL_BIT 0x40000000
832# endif
833# ifndef __X32_SYSCALL_MASK
834# define __X32_SYSCALL_MASK __X32_SYSCALL_BIT
835# endif
836
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200837 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200838 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
839 return -1;
840 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +0000841
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200842 /* Check CS register value. On x86-64 linux it is:
843 * 0x33 for long mode (64 bit)
844 * 0x23 for compatibility mode (32 bit)
H.J. Lu35be5812012-04-16 13:00:01 +0200845 * Check DS register value. On x86-64 linux it is:
846 * 0x2b for x32 mode (x86-64 in 32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200847 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200848 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200849 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +0200850 case 0x33:
851 if (x86_64_regs.ds == 0x2b) {
852 currpers = 2;
853 scno &= ~__X32_SYSCALL_MASK;
854 } else
855 currpers = 0;
856 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200857 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200858 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200859 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200860 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200861 currpers = current_personality;
862 break;
863 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100864# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200865 /* This version analyzes the opcode of a syscall instruction.
866 * (int 0x80 on i386 vs. syscall on x86-64)
867 * It works, but is too complicated.
868 */
869 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +0000870
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200871 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +0000872
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200873 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
874 rip -= 2;
875 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +0000876
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200877 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200878 if (errno)
879 fprintf(stderr, "ptrace_peektext failed: %s\n",
880 strerror(errno));
881 switch (call & 0xffff) {
882 /* x86-64: syscall = 0x0f 0x05 */
883 case 0x050f: currpers = 0; break;
884 /* i386: int 0x80 = 0xcd 0x80 */
885 case 0x80cd: currpers = 1; break;
886 default:
887 currpers = current_personality;
888 fprintf(stderr,
889 "Unknown syscall opcode (0x%04X) while "
890 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200891 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200892 break;
893 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100894# endif
H.J. Lu35be5812012-04-16 13:00:01 +0200895# ifdef X32
H.J. Lu085e4282012-04-17 11:05:04 -0700896 /* Value of currpers:
897 * 0: 64 bit
898 * 1: 32 bit
899 * 2: X32
900 * Value of current_personality:
901 * 0: X32
902 * 1: 32 bit
903 */
904 switch (currpers) {
905 case 0:
906 fprintf(stderr, "syscall_%lu (...) in unsupported "
907 "64-bit mode of process PID=%d\n",
908 scno, tcp->pid);
909 return 0;
910 case 2:
911 currpers = 0;
H.J. Lu35be5812012-04-16 13:00:01 +0200912 }
H.J. Lu35be5812012-04-16 13:00:01 +0200913# endif
H.J. Lu085e4282012-04-17 11:05:04 -0700914 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100915#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000916# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200917 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000918 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200919 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200920 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200921 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000922 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200923 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000924 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200925 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000926#elif defined(AARCH64)
927 struct iovec io;
928 char buf[sizeof(aarch64_regs)];
929 io.iov_base = &buf;
930 io.iov_len = sizeof(aarch64_regs);
931 if (ptrace(PTRACE_GETREGSET, tcp->pid, NT_PRSTATUS, (void *)&io) == -1)
932 return -1;
933 switch (io.iov_len) {
934 case sizeof(aarch64_regs):
935 /* We are in 64-bit mode */
936 memcpy(&aarch64_regs, buf, sizeof(aarch64_regs));
937 scno = aarch64_regs.regs[8];
938 update_personality(tcp, 1);
939 break;
940 case sizeof(regs):
941 /* We are in 32-bit mode */
942 memcpy(&regs, buf, sizeof(regs));
943 scno = regs.uregs[7];
944 update_personality(tcp, 0);
945 break;
946 default:
947 return -1;
948 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100949#elif defined(ARM)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200950 /* Read complete register set in one go. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000951 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +0000952 return -1;
953
954 /*
955 * We only need to grab the syscall number on syscall entry.
956 */
957 if (regs.ARM_ip == 0) {
958 /*
959 * Note: we only deal with only 32-bit CPUs here.
960 */
961 if (regs.ARM_cpsr & 0x20) {
962 /*
963 * Get the Thumb-mode system call number
964 */
965 scno = regs.ARM_r7;
966 } else {
967 /*
968 * Get the ARM-mode system call number
969 */
970 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000971 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +0000972 if (errno)
973 return -1;
974
Roland McGrathf691bd22006-04-25 07:34:41 +0000975 /* Handle the EABI syscall convention. We do not
976 bother converting structures between the two
977 ABIs, but basic functionality should work even
978 if strace and the traced program have different
979 ABIs. */
980 if (scno == 0xef000000) {
981 scno = regs.ARM_r7;
982 } else {
983 if ((scno & 0x0ff00000) != 0x0f900000) {
984 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
985 scno);
986 return -1;
987 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000988
Roland McGrathf691bd22006-04-25 07:34:41 +0000989 /*
990 * Fixup the syscall number
991 */
992 scno &= 0x000fffff;
993 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000994 }
Roland McGrath56703312008-05-20 01:35:55 +0000995 if (scno & 0x0f0000) {
996 /*
997 * Handle ARM specific syscall
998 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000999 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +00001000 scno &= 0x0000ffff;
1001 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001002 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001003
Roland McGrath0f87c492003-06-03 23:29:04 +00001004 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001005 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1006 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001007 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001008#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001009 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001010 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001011#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001012 unsigned long long regs[38];
1013
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001014 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001015 return -1;
1016 a3 = regs[REG_A3];
1017 r2 = regs[REG_V0];
1018
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001019 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001020 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001021 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001022 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001023 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001024 return 0;
1025 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001026 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001027#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001028 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001029 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001030 if (upeek(tcp, REG_V0, &scno) < 0)
1031 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001032
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001033 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001034 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001035 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001036 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001037 return 0;
1038 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001039 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001040#elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001041 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001042 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001043 if (upeek(tcp, REG_R0, &scno) < 0)
1044 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001045
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001046 /*
1047 * Do some sanity checks to figure out if it's
1048 * really a syscall entry
1049 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001050 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001051 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001052 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001053 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001054 return 0;
1055 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001056 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001057#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001058 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001059 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001060 return -1;
1061
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001062 /* Disassemble the syscall trap. */
1063 /* Retrieve the syscall trap instruction. */
1064 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001065# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001066 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1067 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001068# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001069 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001070# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001071 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001072 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001073
1074 /* Disassemble the trap to see what personality to use. */
1075 switch (trap) {
1076 case 0x91d02010:
1077 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001078 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001079 break;
1080 case 0x91d0206d:
1081 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001082 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001083 break;
1084 case 0x91d02000:
1085 /* SunOS syscall trap. (pers 1) */
1086 fprintf(stderr, "syscall: SunOS no support\n");
1087 return -1;
1088 case 0x91d02008:
1089 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001090 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001091 break;
1092 case 0x91d02009:
1093 /* NetBSD/FreeBSD syscall trap. */
1094 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1095 return -1;
1096 case 0x91d02027:
1097 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001098 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001099 break;
1100 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001101# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001102 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001103# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001104 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001105# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001106 return -1;
1107 }
1108
1109 /* Extract the system call number from the registers. */
1110 if (trap == 0x91d02027)
1111 scno = 156;
1112 else
1113 scno = regs.u_regs[U_REG_G1];
1114 if (scno == 0) {
1115 scno = regs.u_regs[U_REG_O0];
1116 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1117 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001118#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001119 if (upeek(tcp, PT_GR20, &scno) < 0)
1120 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001121#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001122 /*
1123 * In the new syscall ABI, the system call number is in R3.
1124 */
1125 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1126 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001127
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001128 if (scno < 0) {
1129 /* Odd as it may seem, a glibc bug has been known to cause
1130 glibc to issue bogus negative syscall numbers. So for
1131 our purposes, make strace print what it *should* have been */
1132 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001133 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001134 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001135 "Detected glibc bug: bogus system call"
1136 " number = %ld, correcting to %ld\n",
1137 scno,
1138 correct_scno);
1139 scno = correct_scno;
1140 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001141#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001142 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001143 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001144 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001145#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001146 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1147 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001148#elif defined(TILE)
Chris Metcalfc8c66982009-12-28 10:00:15 -05001149 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1150 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001151#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001152 if (upeek(tcp, 0, &scno) < 0)
1153 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001154#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001155
Denys Vlasenko523635f2012-02-25 02:44:25 +01001156#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001157 /* new syscall ABI returns result in R0 */
1158 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1159 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001160#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001161 /* ABI defines result returned in r9 */
1162 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1163 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001164#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001165
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001166 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001167 return 1;
1168}
1169
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001170/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001171 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001172 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1173 * 1: ok, continue in trace_syscall_entering().
1174 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001175 * ("????" etc) and bail out.
1176 */
Roland McGratha4d48532005-06-08 20:45:28 +00001177static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001178syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001179{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001180 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001181#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001182 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001183 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001184 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1185 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001186 }
H.J. Lu35be5812012-04-16 13:00:01 +02001187#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001188 {
1189 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001190 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001191 rax = (int)rax; /* sign extend from 32 bits */
1192 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001193 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001194 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1195 return 0;
1196 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001197 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001198#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001199 /* TODO: we already fetched PT_GPR2 in get_scno
1200 * and stored it in syscall_mode, reuse it here
1201 * instead of re-fetching?
1202 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001203 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001204 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001205 if (syscall_mode != -ENOSYS)
1206 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001207 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001208 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001209 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001210 return 0;
1211 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001212#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001213 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001214 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001215 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001216 if (d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001217 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001218 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001219 return 0;
1220 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001221#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001222 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001223 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001224 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001225 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001226 if (ia32 && r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001227 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001228 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001229 return 0;
1230 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001231#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001232 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001233 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001234 if (r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001235 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001236 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001237 return 0;
1238 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001239#elif defined(MICROBLAZE)
1240 if (upeek(tcp, 3 * 4, &r3) < 0)
1241 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001242 if (r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001243 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001244 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001245 return 0;
1246 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001247#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001248 return 1;
1249}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001250
Denys Vlasenko146b9442012-03-18 22:10:48 +01001251static void
1252internal_fork(struct tcb *tcp)
1253{
1254#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1255# define ARG_FLAGS 1
1256#else
1257# define ARG_FLAGS 0
1258#endif
1259#ifndef CLONE_UNTRACED
1260# define CLONE_UNTRACED 0x00800000
1261#endif
1262 if ((ptrace_setoptions
1263 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1264 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1265 return;
1266
1267 if (!followfork)
1268 return;
1269
1270 if (entering(tcp)) {
1271 /*
1272 * We won't see the new child if clone is called with
1273 * CLONE_UNTRACED, so we keep the same logic with that option
1274 * and don't trace it.
1275 */
1276 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1277 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1278 return;
1279 setbpt(tcp);
1280 } else {
1281 if (tcp->flags & TCB_BPTSET)
1282 clearbpt(tcp);
1283 }
1284}
1285
1286#if defined(TCB_WAITEXECVE)
1287static void
1288internal_exec(struct tcb *tcp)
1289{
1290 /* Maybe we have post-execve SIGTRAP suppressed? */
1291 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1292 return; /* yes, no need to do anything */
1293
1294 if (exiting(tcp) && syserror(tcp))
1295 /* Error in execve, no post-execve SIGTRAP expected */
1296 tcp->flags &= ~TCB_WAITEXECVE;
1297 else
1298 tcp->flags |= TCB_WAITEXECVE;
1299}
1300#endif
1301
1302static void
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001303internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001304{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001305 /*
1306 * We must always trace a few critical system calls in order to
1307 * correctly support following forks in the presence of tracing
1308 * qualifiers.
1309 */
1310 int (*func)();
1311
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001312 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001313 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001314
1315 func = sysent[tcp->scno].sys_func;
1316
1317 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001318 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001319 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001320 ) {
1321 internal_fork(tcp);
1322 return;
1323 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001324
Denys Vlasenko84703742012-02-25 02:38:52 +01001325#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001326 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001327# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001328 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001329# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001330 ) {
1331 internal_exec(tcp);
1332 return;
1333 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001334#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001335}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001336
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001337/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001338static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001339get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001340{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001341 int i, nargs;
1342
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001343 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001344 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001345 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001346 nargs = tcp->u_nargs = MAX_ARGS;
1347
Denys Vlasenko523635f2012-02-25 02:44:25 +01001348#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001349 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001350 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1351 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001352#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001353 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001354 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1355 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001356#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001357 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001358 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001359 long rbs_end;
1360 /* be backwards compatible with kernel < 2.4.4... */
1361# ifndef PT_RBS_END
1362# define PT_RBS_END PT_AR_BSP
1363# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001364
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001365 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1366 return -1;
1367 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001368 return -1;
1369
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001370 sof = (cfm >> 0) & 0x7f;
1371 sol = (cfm >> 7) & 0x7f;
1372 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1373
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001374 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001375 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1376 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1377 return -1;
1378 }
1379 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001380 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1381 PT_R9 /* ECX = out1 */,
1382 PT_R10 /* EDX = out2 */,
1383 PT_R14 /* ESI = out3 */,
1384 PT_R15 /* EDI = out4 */,
1385 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001386
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001387 for (i = 0; i < nargs; ++i) {
1388 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1389 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001390 /* truncate away IVE sign-extension */
1391 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001392 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001393 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001394#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001395 /* N32 and N64 both use up to six registers. */
1396 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001397
1398 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1399 return -1;
1400
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001401 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001402 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001403# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001404 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001405# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001406 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001407#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001408 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001409 long sp;
1410
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001411 if (upeek(tcp, REG_SP, &sp) < 0)
1412 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001413 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001414 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1415 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001416 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001417 (char *)(tcp->u_arg + 4));
1418 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001419 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001420 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001421 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001422 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001423#elif defined(POWERPC)
1424# ifndef PT_ORIG_R3
1425# define PT_ORIG_R3 34
1426# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001427 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001428 if (upeek(tcp, (i==0) ?
1429 (sizeof(unsigned long) * PT_ORIG_R3) :
1430 ((i+PT_R3) * sizeof(unsigned long)),
1431 &tcp->u_arg[i]) < 0)
1432 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001433 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001434#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001435 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001436 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001437#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001438 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001439 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1440 return -1;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001441#elif defined(ARM) || defined(AARCH64)
1442# if defined(AARCH64)
1443 if (tcp->currpers == 1)
1444 for (i = 0; i < nargs; ++i)
1445 tcp->u_arg[i] = aarch64_regs.regs[i];
1446 else
1447# endif /* AARCH64 */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001448 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001449 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001450#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001451 (void)i;
1452 (void)nargs;
1453 tcp->u_arg[0] = regs.r12;
1454 tcp->u_arg[1] = regs.r11;
1455 tcp->u_arg[2] = regs.r10;
1456 tcp->u_arg[3] = regs.r9;
1457 tcp->u_arg[4] = regs.r5;
1458 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001459#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001460 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 +02001461
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001462 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001463 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1464 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001465#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001466 static const int syscall_regs[MAX_ARGS] = {
1467 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1468 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001469 };
1470
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001471 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001472 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001473 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001474#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001475 int i;
1476 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001477 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001478
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001479 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001480 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1481 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001482#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001483 (void)i;
1484 (void)nargs;
H.J. Lu35be5812012-04-16 13:00:01 +02001485 if (current_personality != 1) { /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001486 tcp->u_arg[0] = x86_64_regs.rdi;
1487 tcp->u_arg[1] = x86_64_regs.rsi;
1488 tcp->u_arg[2] = x86_64_regs.rdx;
1489 tcp->u_arg[3] = x86_64_regs.r10;
1490 tcp->u_arg[4] = x86_64_regs.r8;
1491 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001492# ifdef X32
1493 tcp->ext_arg[0] = x86_64_regs.rdi;
1494 tcp->ext_arg[1] = x86_64_regs.rsi;
1495 tcp->ext_arg[2] = x86_64_regs.rdx;
1496 tcp->ext_arg[3] = x86_64_regs.r10;
1497 tcp->ext_arg[4] = x86_64_regs.r8;
1498 tcp->ext_arg[5] = x86_64_regs.r9;
1499# endif
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001500 } else { /* i386 ABI */
1501 /* Sign-extend lower 32 bits */
1502 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1503 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1504 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1505 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1506 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1507 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1508 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001509#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001510 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001511 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1512 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001513#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001514 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001515 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001516 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001517 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001518
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001519 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001520 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1521 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001522#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001523 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001524 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1525 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001526#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001527 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001528 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1529 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001530#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001531 (void)i;
1532 (void)nargs;
1533 tcp->u_arg[0] = i386_regs.ebx;
1534 tcp->u_arg[1] = i386_regs.ecx;
1535 tcp->u_arg[2] = i386_regs.edx;
1536 tcp->u_arg[3] = i386_regs.esi;
1537 tcp->u_arg[4] = i386_regs.edi;
1538 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001539#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001540 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001541 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1542 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001543#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001544 return 1;
1545}
1546
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001547static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001548trace_syscall_entering(struct tcb *tcp)
1549{
1550 int res, scno_good;
1551
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001552#if defined TCB_WAITEXECVE
1553 if (tcp->flags & TCB_WAITEXECVE) {
1554 /* This is the post-execve SIGTRAP. */
1555 tcp->flags &= ~TCB_WAITEXECVE;
1556 return 0;
1557 }
1558#endif
1559
Denys Vlasenko06602d92011-08-24 17:53:52 +02001560 scno_good = res = get_scno(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001561 if (res == 0)
1562 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001563 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001564 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001565 if (res == 0)
1566 return res;
1567 if (res == 1)
1568 res = get_syscall_args(tcp);
1569 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001570
1571 if (res != 1) {
1572 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001573 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001574 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001575 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001576 tprintf("syscall_%lu(", tcp->scno);
1577 else
1578 tprintf("%s(", sysent[tcp->scno].sys_name);
1579 /*
1580 * " <unavailable>" will be added later by the code which
1581 * detects ptrace errors.
1582 */
1583 goto ret;
1584 }
1585
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001586#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1587 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001588# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001589 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001590 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001591 break;
1592 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001593# endif
1594# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001595 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001596 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001597 break;
1598 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001599# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001600 break;
1601 }
1602#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1603
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001604 internal_syscall(tcp);
1605
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001606 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001607 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1608 (tracing_paths && !pathtrace_match(tcp))) {
1609 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1610 return 0;
1611 }
1612
1613 tcp->flags &= ~TCB_FILTERED;
1614
1615 if (cflag == CFLAG_ONLY_STATS) {
1616 res = 0;
1617 goto ret;
1618 }
1619
1620 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001621 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001622 tprintf("syscall_%lu(", tcp->scno);
1623 else
1624 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001625 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001626 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1627 sysent[tcp->scno].sys_func != sys_exit))
1628 res = printargs(tcp);
1629 else
1630 res = (*sysent[tcp->scno].sys_func)(tcp);
1631
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001632 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001633 ret:
1634 tcp->flags |= TCB_INSYSCALL;
1635 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001636 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001637 gettimeofday(&tcp->etime, NULL);
1638 return res;
1639}
1640
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001641/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001642 * 1: ok, continue in trace_syscall_exiting().
1643 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001644 * ("????" etc) and bail out.
1645 */
1646static int
1647get_syscall_result(struct tcb *tcp)
1648{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001649#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001650 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1651 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001652#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001653# define SO_MASK 0x10000000
1654 {
1655 long flags;
1656 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1657 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001658 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001659 return -1;
1660 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001661 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001662 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001663#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001664 /* Read complete register set in one go. */
1665 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1666 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001667#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001668 if (upeek(tcp, PT_R0, &r0) < 0)
1669 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001670#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001671 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001672 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001673#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001674 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001675 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001676#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001677# define IA64_PSR_IS ((long)1 << 34)
1678 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1679 ia32 = (psr & IA64_PSR_IS) != 0;
1680 if (upeek(tcp, PT_R8, &r8) < 0)
1681 return -1;
1682 if (upeek(tcp, PT_R10, &r10) < 0)
1683 return -1;
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001684#elif defined(AARCH64)
1685 struct iovec io;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001686 char buf[sizeof(aarch64_regs)];
1687 io.iov_base = &buf;
1688 io.iov_len = sizeof(aarch64_regs);
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001689 if (ptrace(PTRACE_GETREGSET, tcp->pid, NT_PRSTATUS, (void *)&io) == -1)
1690 return -1;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001691 switch (io.iov_len) {
1692 case sizeof(aarch64_regs):
1693 /* We are in 64-bit mode */
1694 memcpy(&aarch64_regs, buf, sizeof(aarch64_regs));
1695 update_personality(tcp, 1);
1696 break;
1697 case sizeof(regs):
1698 /* We are in 32-bit mode */
1699 memcpy(&regs, buf, sizeof(regs));
1700 update_personality(tcp, 0);
1701 break;
1702 default:
1703 return -1;
1704 }
1705#elif defined(ARM)
1706 /* Read complete ARM register set in one go. */
1707 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1708 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001709#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001710 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1711 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001712#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001713 unsigned long long regs[38];
1714
1715 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1716 return -1;
1717 a3 = regs[REG_A3];
1718 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001719#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001720 if (upeek(tcp, REG_A3, &a3) < 0)
1721 return -1;
1722 if (upeek(tcp, REG_V0, &r2) < 0)
1723 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001724#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001725 if (upeek(tcp, REG_A3, &a3) < 0)
1726 return -1;
1727 if (upeek(tcp, REG_R0, &r0) < 0)
1728 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001729#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001730 /* Everything we need is in the current register set. */
1731 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1732 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001733#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001734 if (upeek(tcp, PT_GR28, &r28) < 0)
1735 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001736#elif defined(SH)
1737#elif defined(SH64)
1738#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001739 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1740 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001741#elif defined(TILE)
1742#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001743 if (upeek(tcp, 3 * 4, &r3) < 0)
1744 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001745#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001746
Denys Vlasenko523635f2012-02-25 02:44:25 +01001747#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001748 /* new syscall ABI returns result in R0 */
1749 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1750 return -1;
1751#elif defined(SH64)
1752 /* ABI defines result returned in r9 */
1753 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1754 return -1;
1755#endif
1756
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001757 return 1;
1758}
1759
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001760/* Called at each syscall exit */
1761static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001762syscall_fixup_on_sysexit(struct tcb *tcp)
1763{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001764#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001765 if (syscall_mode != -ENOSYS)
1766 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001767 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001768 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1769 /*
1770 * Return from execve.
1771 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1772 * flag set for the post-execve SIGTRAP to see and reset.
1773 */
1774 gpr2 = 0;
1775 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001776#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001777}
1778
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001779/*
1780 * Check the syscall return value register value for whether it is
1781 * a negated errno code indicating an error, or a success return value.
1782 */
1783static inline int
1784is_negated_errno(unsigned long int val)
1785{
1786 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001787#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001788 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001789 val = (unsigned int) val;
1790 max = (unsigned int) max;
1791 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001792#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001793 return val > max;
1794}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001795
Denys Vlasenko907735a2012-03-21 00:23:16 +01001796/* Returns:
1797 * 1: ok, continue in trace_syscall_exiting().
1798 * -1: error, trace_syscall_exiting() should print error indicator
1799 * ("????" etc) and bail out.
1800 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001801static int
1802get_error(struct tcb *tcp)
1803{
1804 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001805 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001806 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001807 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1808 check_errno = 0;
1809 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001810#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001811 if (check_errno && is_negated_errno(gpr2)) {
1812 tcp->u_rval = -1;
1813 u_error = -gpr2;
1814 }
1815 else {
1816 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001817 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001818#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001819 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001820 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001821 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001822 }
1823 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001824 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001825 }
H.J. Lu35be5812012-04-16 13:00:01 +02001826#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001827 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001828 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001829 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001830 }
1831 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001832 tcp->u_rval = x86_64_regs.rax;
H.J. Lu35be5812012-04-16 13:00:01 +02001833# if defined(X32)
1834 tcp->u_lrval = x86_64_regs.rax;
1835# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001836 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001837#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001838 if (ia32) {
1839 int err;
1840
1841 err = (int)r8;
1842 if (check_errno && is_negated_errno(err)) {
1843 tcp->u_rval = -1;
1844 u_error = -err;
1845 }
1846 else {
1847 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001848 }
1849 } else {
1850 if (check_errno && r10) {
1851 tcp->u_rval = -1;
1852 u_error = r8;
1853 } else {
1854 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001855 }
1856 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001857#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001858 if (check_errno && a3) {
1859 tcp->u_rval = -1;
1860 u_error = r2;
1861 } else {
1862 tcp->u_rval = r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02001863# if defined(LINUX_MIPSN32)
1864 tcp->u_lrval = r2;
1865# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001866 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001867#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001868 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001869 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001870 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001871 }
1872 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001873 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001874 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001875#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001876 if (check_errno && is_negated_errno(d0)) {
1877 tcp->u_rval = -1;
1878 u_error = -d0;
1879 }
1880 else {
1881 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001882 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001883#elif defined(ARM) || defined(AARCH64)
1884# if defined(AARCH64)
1885 if (tcp->currpers == 1) {
1886 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
1887 tcp->u_rval = -1;
1888 u_error = -aarch64_regs.regs[0];
1889 }
1890 else {
1891 tcp->u_rval = aarch64_regs.regs[0];
1892 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001893 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001894 else
1895# endif /* AARCH64 */
1896 {
1897 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1898 tcp->u_rval = -1;
1899 u_error = -regs.ARM_r0;
1900 }
1901 else {
1902 tcp->u_rval = regs.ARM_r0;
1903 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001904 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001905#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001906 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1907 tcp->u_rval = -1;
1908 u_error = -regs.r12;
1909 }
1910 else {
1911 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001912 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001913#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001914 if (check_errno && is_negated_errno(r0)) {
1915 tcp->u_rval = -1;
1916 u_error = -r0;
1917 } else {
1918 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001919 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001920#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001921 if (check_errno && a3) {
1922 tcp->u_rval = -1;
1923 u_error = r0;
1924 }
1925 else {
1926 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001927 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001928#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001929 if (check_errno && regs.psr & PSR_C) {
1930 tcp->u_rval = -1;
1931 u_error = regs.u_regs[U_REG_O0];
1932 }
1933 else {
1934 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001935 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001936#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001937 if (check_errno && regs.tstate & 0x1100000000UL) {
1938 tcp->u_rval = -1;
1939 u_error = regs.u_regs[U_REG_O0];
1940 }
1941 else {
1942 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001943 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001944#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001945 if (check_errno && is_negated_errno(r28)) {
1946 tcp->u_rval = -1;
1947 u_error = -r28;
1948 }
1949 else {
1950 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001951 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001952#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001953 if (check_errno && is_negated_errno(r0)) {
1954 tcp->u_rval = -1;
1955 u_error = -r0;
1956 }
1957 else {
1958 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001959 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001960#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001961 if (check_errno && is_negated_errno(r9)) {
1962 tcp->u_rval = -1;
1963 u_error = -r9;
1964 }
1965 else {
1966 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001967 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001968#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001969 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1970 tcp->u_rval = -1;
1971 u_error = -r10;
1972 }
1973 else {
1974 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001975 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001976#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001977 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001978 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1979 return -1;
1980 if (check_errno && rval < 0 && rval > -nerrnos) {
1981 tcp->u_rval = -1;
1982 u_error = -rval;
1983 }
1984 else {
1985 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001986 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001987#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001988 if (check_errno && is_negated_errno(r3)) {
1989 tcp->u_rval = -1;
1990 u_error = -r3;
1991 }
1992 else {
1993 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001994 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001995#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001996 tcp->u_error = u_error;
1997 return 1;
1998}
1999
2000static void
2001dumpio(struct tcb *tcp)
2002{
2003 if (syserror(tcp))
2004 return;
2005 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
2006 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002007 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002008 return;
2009 if (sysent[tcp->scno].sys_func == printargs)
2010 return;
2011 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
2012 if (sysent[tcp->scno].sys_func == sys_read ||
2013 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002014 sysent[tcp->scno].sys_func == sys_recv ||
2015 sysent[tcp->scno].sys_func == sys_recvfrom)
2016 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
2017 else if (sysent[tcp->scno].sys_func == sys_readv)
2018 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2019 return;
2020 }
2021 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
2022 if (sysent[tcp->scno].sys_func == sys_write ||
2023 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002024 sysent[tcp->scno].sys_func == sys_send ||
2025 sysent[tcp->scno].sys_func == sys_sendto)
2026 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
2027 else if (sysent[tcp->scno].sys_func == sys_writev)
2028 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2029 return;
2030 }
2031}
2032
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002033static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002034trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002035{
2036 int sys_res;
2037 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002038 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002039 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002040
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002041 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002042 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002043 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002044
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002045#if SUPPORTED_PERSONALITIES > 1
2046 update_personality(tcp, tcp->currpers);
2047#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002048 res = get_syscall_result(tcp);
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002049 if (res == 1) {
2050 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01002051 res = get_error(tcp); /* returns 1 or -1 */
2052 if (res == 1) {
2053 internal_syscall(tcp);
2054 if (filtered(tcp)) {
2055 goto ret;
2056 }
2057 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002058 }
2059
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002060 if (cflag) {
2061 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002062 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002063 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002064 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002065 }
2066 }
2067
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002068 /* If not in -ff mode, and printing_tcp != tcp,
2069 * then the log currently does not end with output
2070 * of _our syscall entry_, but with something else.
2071 * We need to say which syscall's return is this.
2072 *
2073 * Forced reprinting via TCB_REPRINT is used only by
2074 * "strace -ff -oLOG test/threaded_execve" corner case.
2075 * It's the only case when -ff mode needs reprinting.
2076 */
2077 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2078 tcp->flags &= ~TCB_REPRINT;
2079 printleader(tcp);
2080 if (!SCNO_IN_RANGE(tcp->scno))
2081 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2082 else
2083 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2084 }
2085 printing_tcp = tcp;
2086
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002087 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002088 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002089 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002090 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002091 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002092 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002093 tcp->flags &= ~TCB_INSYSCALL;
2094 return res;
2095 }
2096
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002097 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002098 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002099 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002100 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002101 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002102 /* FIXME: not_failing_only (IOW, option -z) is broken:
2103 * failure of syscall is known only after syscall return.
2104 * Thus we end up with something like this on, say, ENOENT:
2105 * open("doesnt_exist", O_RDONLY <unfinished ...>
2106 * {next syscall decode}
2107 * whereas the intended result is that open(...) line
2108 * is not shown at all.
2109 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002110 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002111 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002112 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2113 }
2114
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002115 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002116 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002117 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002118 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002119 qual_flags[tcp->scno] & QUAL_RAW) {
2120 if (u_error)
2121 tprintf("= -1 (errno %ld)", u_error);
2122 else
2123 tprintf("= %#lx", tcp->u_rval);
2124 }
2125 else if (!(sys_res & RVAL_NONE) && u_error) {
2126 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002127 /* Blocked signals do not interrupt any syscalls.
2128 * In this case syscalls don't return ERESTARTfoo codes.
2129 *
2130 * Deadly signals set to SIG_DFL interrupt syscalls
2131 * and kill the process regardless of which of the codes below
2132 * is returned by the interrupted syscall.
2133 * In some cases, kernel forces a kernel-generated deadly
2134 * signal to be unblocked and set to SIG_DFL (and thus cause
2135 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2136 * or SIGILL. (The alternative is to leave process spinning
2137 * forever on the faulty instruction - not useful).
2138 *
2139 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2140 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2141 * but kernel will always restart them.
2142 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002143 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002144 /* Most common type of signal-interrupted syscall exit code.
2145 * The system call will be restarted with the same arguments
2146 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2147 */
2148 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002149 break;
2150 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002151 /* Rare. For example, fork() returns this if interrupted.
2152 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2153 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002154 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002155 break;
2156 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002157 /* pause(), rt_sigsuspend() etc use this code.
2158 * SA_RESTART is ignored (assumed not set):
2159 * syscall won't restart (will return EINTR instead)
2160 * even after signal with SA_RESTART set.
2161 * However, after SIG_IGN or SIG_DFL signal it will.
2162 */
2163 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002164 break;
2165 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002166 /* Syscalls like nanosleep(), poll() which can't be
2167 * restarted with their original arguments use this
2168 * code. Kernel will execute restart_syscall() instead,
2169 * which changes arguments before restarting syscall.
2170 * SA_RESTART is ignored (assumed not set) similarly
2171 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2172 * since restart data is saved in "restart block"
2173 * in task struct, and if signal handler uses a syscall
2174 * which in turn saves another such restart block,
2175 * old data is lost and restart becomes impossible)
2176 */
2177 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002178 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002179 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002180 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002181 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002182 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002183 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002184 strerror(u_error));
2185 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002186 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002187 strerror(u_error));
2188 break;
2189 }
2190 if ((sys_res & RVAL_STR) && tcp->auxstr)
2191 tprintf(" (%s)", tcp->auxstr);
2192 }
2193 else {
2194 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002195 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002196 else {
2197 switch (sys_res & RVAL_MASK) {
2198 case RVAL_HEX:
2199 tprintf("= %#lx", tcp->u_rval);
2200 break;
2201 case RVAL_OCTAL:
2202 tprintf("= %#lo", tcp->u_rval);
2203 break;
2204 case RVAL_UDECIMAL:
2205 tprintf("= %lu", tcp->u_rval);
2206 break;
2207 case RVAL_DECIMAL:
2208 tprintf("= %ld", tcp->u_rval);
2209 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002210#if defined(LINUX_MIPSN32) || defined(X32)
2211 /*
2212 case RVAL_LHEX:
2213 tprintf("= %#llx", tcp->u_lrval);
2214 break;
2215 case RVAL_LOCTAL:
2216 tprintf("= %#llo", tcp->u_lrval);
2217 break;
2218 */
2219 case RVAL_LUDECIMAL:
2220 tprintf("= %llu", tcp->u_lrval);
2221 break;
2222 /*
2223 case RVAL_LDECIMAL:
2224 tprintf("= %lld", tcp->u_lrval);
2225 break;
2226 */
2227#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002228 default:
2229 fprintf(stderr,
2230 "invalid rval format\n");
2231 break;
2232 }
2233 }
2234 if ((sys_res & RVAL_STR) && tcp->auxstr)
2235 tprintf(" (%s)", tcp->auxstr);
2236 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002237 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002238 tv_sub(&tv, &tv, &tcp->etime);
2239 tprintf(" <%ld.%06ld>",
2240 (long) tv.tv_sec, (long) tv.tv_usec);
2241 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002242 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002243 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002244 line_ended();
2245
Denys Vlasenko3b738812011-08-22 02:06:35 +02002246 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002247 tcp->flags &= ~TCB_INSYSCALL;
2248 return 0;
2249}
2250
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002251int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002252trace_syscall(struct tcb *tcp)
2253{
2254 return exiting(tcp) ?
2255 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2256}