blob: 87a66fc2f0d67f3709daffe7ca3c06f4556786c3 [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 val = regs.u_regs[U_REG_O1];
622#elif defined(SH)
623 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
624 return -1;
625#elif defined(IA64)
626 if (upeek(tcp, PT_R9, &val) < 0)
627 return -1;
628#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200629
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200630 return val;
631}
632
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200633int
634is_restart_error(struct tcb *tcp)
635{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200636 switch (tcp->u_error) {
637 case ERESTARTSYS:
638 case ERESTARTNOINTR:
639 case ERESTARTNOHAND:
640 case ERESTART_RESTARTBLOCK:
641 return 1;
642 default:
643 break;
644 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200645 return 0;
646}
647
Denys Vlasenko523635f2012-02-25 02:44:25 +0100648#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100649struct pt_regs i386_regs;
H.J. Lu35be5812012-04-16 13:00:01 +0200650#elif defined(X86_64) || defined(X32)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100651/*
652 * On 32 bits, pt_regs and user_regs_struct are the same,
653 * but on 64 bits, user_regs_struct has six more fields:
654 * fs_base, gs_base, ds, es, fs, gs.
655 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
656 */
657static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100658#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200659long r8, r10, psr; /* TODO: make static? */
660long ia32 = 0; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100661#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +0100662static long ppc_result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100663#elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200664static long d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100665#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200666static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100667#elif defined(ARM)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100668struct pt_regs regs; /* not static */
Steve McIntyred8d3bd32012-10-24 17:58:16 +0100669#elif defined(AARCH64)
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000670static struct user_pt_regs aarch64_regs;
671static struct arm_pt_regs regs;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100672static struct iovec aarch64_io = {
673 .iov_base = &aarch64_regs
674};
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 Vlasenkoce7d9532013-02-05 16:36:13 +0100681struct pt_regs regs; /* not static */
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200682static 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 Vlasenkoce7d9532013-02-05 16:36:13 +0100705void
706printcall(struct tcb *tcp)
707{
708#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
709 sizeof(long) == 8 ? "[????????????????] " : \
710 NULL /* crash */)
711 if (get_regs_error) {
712 PRINTBADPC;
713 return;
714 }
715#if defined(I386)
716 tprintf("[%08lx] ", i386_regs.eip);
717#elif defined(S390) || defined(S390X)
718 long psw;
719 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
720 PRINTBADPC;
721 return;
722 }
723# ifdef S390
724 tprintf("[%08lx] ", psw);
725# elif S390X
726 tprintf("[%16lx] ", psw);
727# endif
728#elif defined(X86_64) || defined(X32)
729 tprintf("[%16lx] ", x86_64_regs.ip);
730#elif defined(IA64)
731 long ip;
732
733 if (upeek(tcp, PT_B0, &ip) < 0) {
734 PRINTBADPC;
735 return;
736 }
737 tprintf("[%08lx] ", ip);
738#elif defined(POWERPC)
739 long pc;
740
741 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
742 PRINTBADPC;
743 return;
744 }
745# ifdef POWERPC64
746 tprintf("[%016lx] ", pc);
747# else
748 tprintf("[%08lx] ", pc);
749# endif
750#elif defined(M68K)
751 long pc;
752
753 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
754 tprints("[????????] ");
755 return;
756 }
757 tprintf("[%08lx] ", pc);
758#elif defined(ALPHA)
759 long pc;
760
761 if (upeek(tcp, REG_PC, &pc) < 0) {
762 tprints("[????????????????] ");
763 return;
764 }
765 tprintf("[%08lx] ", pc);
766#elif defined(SPARC)
767 tprintf("[%08lx] ", regs.pc);
768#elif defined(SPARC64)
769 tprintf("[%08lx] ", regs.tpc);
770#elif defined(HPPA)
771 long pc;
772
773 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
774 tprints("[????????] ");
775 return;
776 }
777 tprintf("[%08lx] ", pc);
778#elif defined(MIPS)
779 long pc;
780
781 if (upeek(tcp, REG_EPC, &pc) < 0) {
782 tprints("[????????] ");
783 return;
784 }
785 tprintf("[%08lx] ", pc);
786#elif defined(SH)
787 long pc;
788
789 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
790 tprints("[????????] ");
791 return;
792 }
793 tprintf("[%08lx] ", pc);
794#elif defined(SH64)
795 long pc;
796
797 if (upeek(tcp, REG_PC, &pc) < 0) {
798 tprints("[????????????????] ");
799 return;
800 }
801 tprintf("[%08lx] ", pc);
802#elif defined(ARM)
803 tprintf("[%08lx] ", regs.ARM_pc);
804/*#elif defined(AARCH64) ??? */
805#elif defined(AVR32)
806 tprintf("[%08lx] ", regs.pc);
807#elif defined(BFIN)
808 long pc;
809
810 if (upeek(tcp, PT_PC, &pc) < 0) {
811 PRINTBADPC;
812 return;
813 }
814 tprintf("[%08lx] ", pc);
815#elif defined(CRISV10)
816 long pc;
817
818 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
819 PRINTBADPC;
820 return;
821 }
822 tprintf("[%08lx] ", pc);
823#elif defined(CRISV32)
824 long pc;
825
826 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
827 PRINTBADPC;
828 return;
829 }
830 tprintf("[%08lx] ", pc);
831#endif /* architecture */
832}
833
834#ifndef get_regs
835long get_regs_error;
836void get_regs(pid_t pid)
837{
838# if defined(AVR32)
839 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
840# elif defined(I386)
841 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &i386_regs);
842# elif defined(X86_64) || defined(X32)
843 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &x86_64_regs);
844# elif defined(AARCH64)
845 /*aarch64_io.iov_base = &aarch64_regs; - already is */
846 aarch64_io.iov_len = sizeof(aarch64_regs);
847 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void *)&aarch64_io);
848 if (get_regs_error)
849 return;
850 switch (aarch64_io.iov_len) {
851 case sizeof(regs):
852 /* We are in 32-bit mode */
853 memcpy(&regs, &aarch64_regs, sizeof(regs));
854 break;
855 case sizeof(aarch64_regs):
856 /* We are in 64-bit mode */
857 /* Data is already in aarch64_regs */
858 break;
859 default:
860 get_regs_error = -1;
861 break;
862 }
863# elif defined(ARM)
864 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (void *)&regs);
865# elif defined(SPARC) || defined(SPARC64)
866 get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&regs, 0);
867# endif
868}
869#endif
870
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200871/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100872 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
873 * 1: ok, continue in trace_syscall_entering().
874 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200875 * ("????" etc) and bail out.
876 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100877static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200878get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000879{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000880 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000881
Denys Vlasenko523635f2012-02-25 02:44:25 +0100882#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000883 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200884 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000885
886 if (syscall_mode != -ENOSYS) {
887 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000888 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000889 */
890 scno = syscall_mode;
891 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000892 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000893 * Old style of "passing" the scno via the SVC instruction.
894 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000895 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200896 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200897 static const int gpr_offset[16] = {
898 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
899 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
900 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
901 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
902 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000903
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000904 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000905 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000906 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000907 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000908 if (errno) {
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000909 perror_msg("%s", "peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000910 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000911 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000912
913 /*
914 * We have to check if the SVC got executed directly or via an
915 * EXECUTE instruction. In case of EXECUTE it is necessary to do
916 * instruction decoding to derive the system call number.
917 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
918 * so that this doesn't work if a SVC opcode is part of an EXECUTE
919 * opcode. Since there is no way to find out the opcode size this
920 * is the best we can do...
921 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000922 if ((opcode & 0xff00) == 0x0a00) {
923 /* SVC opcode */
924 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000925 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000926 else {
927 /* SVC got executed by EXECUTE instruction */
928
929 /*
930 * Do instruction decoding of EXECUTE. If you really want to
931 * understand this, read the Principles of Operations.
932 */
933 svc_addr = (void *) (opcode & 0xfff);
934
935 tmp = 0;
936 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000937 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000938 return -1;
939 svc_addr += tmp;
940
941 tmp = 0;
942 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000943 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000944 return -1;
945 svc_addr += tmp;
946
Denys Vlasenkofb036672009-01-23 16:30:26 +0000947 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000948 if (errno)
949 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100950# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000951 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100952# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000953 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100954# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000955 tmp = 0;
956 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000957 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000958 return -1;
959
960 scno = (scno | tmp) & 0xff;
961 }
962 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100963#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000964 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000965 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100966# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200967 /* TODO: speed up strace by not doing this at every syscall.
968 * We only need to do it after execve.
969 */
970 int currpers;
971 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200972
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200973 /* Check for 64/32 bit mode. */
974 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
975 return -1;
976 /* SF is bit 0 of MSR */
977 if (val < 0)
978 currpers = 0;
979 else
980 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000981 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100982# endif
983#elif defined(AVR32)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200984 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100985#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000986 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000987 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100988#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200989 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +0200990#elif defined(X86_64) || defined(X32)
991# ifndef __X32_SYSCALL_BIT
992# define __X32_SYSCALL_BIT 0x40000000
993# endif
994# ifndef __X32_SYSCALL_MASK
995# define __X32_SYSCALL_MASK __X32_SYSCALL_BIT
996# endif
997
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200998 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200999 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +00001000
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001001 /* Check CS register value. On x86-64 linux it is:
1002 * 0x33 for long mode (64 bit)
1003 * 0x23 for compatibility mode (32 bit)
H.J. Lu35be5812012-04-16 13:00:01 +02001004 * Check DS register value. On x86-64 linux it is:
1005 * 0x2b for x32 mode (x86-64 in 32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001006 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001007 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001008 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +02001009 case 0x33:
1010 if (x86_64_regs.ds == 0x2b) {
1011 currpers = 2;
1012 scno &= ~__X32_SYSCALL_MASK;
1013 } else
1014 currpers = 0;
1015 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001016 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001017 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001018 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001019 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001020 currpers = current_personality;
1021 break;
1022 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001023# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001024 /* This version analyzes the opcode of a syscall instruction.
1025 * (int 0x80 on i386 vs. syscall on x86-64)
1026 * It works, but is too complicated.
1027 */
1028 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +00001029
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001030 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +00001031
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001032 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
1033 rip -= 2;
1034 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +00001035
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001036 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001037 if (errno)
1038 fprintf(stderr, "ptrace_peektext failed: %s\n",
1039 strerror(errno));
1040 switch (call & 0xffff) {
1041 /* x86-64: syscall = 0x0f 0x05 */
1042 case 0x050f: currpers = 0; break;
1043 /* i386: int 0x80 = 0xcd 0x80 */
1044 case 0x80cd: currpers = 1; break;
1045 default:
1046 currpers = current_personality;
1047 fprintf(stderr,
1048 "Unknown syscall opcode (0x%04X) while "
1049 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001050 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001051 break;
1052 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001053# endif
H.J. Lu35be5812012-04-16 13:00:01 +02001054# ifdef X32
H.J. Lu085e4282012-04-17 11:05:04 -07001055 /* Value of currpers:
1056 * 0: 64 bit
1057 * 1: 32 bit
1058 * 2: X32
1059 * Value of current_personality:
1060 * 0: X32
1061 * 1: 32 bit
1062 */
1063 switch (currpers) {
1064 case 0:
1065 fprintf(stderr, "syscall_%lu (...) in unsupported "
1066 "64-bit mode of process PID=%d\n",
1067 scno, tcp->pid);
1068 return 0;
1069 case 2:
1070 currpers = 0;
H.J. Lu35be5812012-04-16 13:00:01 +02001071 }
H.J. Lu35be5812012-04-16 13:00:01 +02001072# endif
H.J. Lu085e4282012-04-17 11:05:04 -07001073 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001074#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001075# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001076 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001077 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001078 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001079 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001080 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001081 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001082 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001083 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001084 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001085#elif defined(AARCH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001086 switch (aarch64_io.iov_len) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001087 case sizeof(aarch64_regs):
1088 /* We are in 64-bit mode */
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001089 scno = aarch64_regs.regs[8];
1090 update_personality(tcp, 1);
1091 break;
1092 case sizeof(regs):
1093 /* We are in 32-bit mode */
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001094 scno = regs.uregs[7];
1095 update_personality(tcp, 0);
1096 break;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001097 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001098#elif defined(ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001099 /*
1100 * We only need to grab the syscall number on syscall entry.
1101 */
1102 if (regs.ARM_ip == 0) {
1103 /*
1104 * Note: we only deal with only 32-bit CPUs here.
1105 */
1106 if (regs.ARM_cpsr & 0x20) {
1107 /*
1108 * Get the Thumb-mode system call number
1109 */
1110 scno = regs.ARM_r7;
1111 } else {
1112 /*
1113 * Get the ARM-mode system call number
1114 */
1115 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +00001116 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +00001117 if (errno)
1118 return -1;
1119
Roland McGrathf691bd22006-04-25 07:34:41 +00001120 /* Handle the EABI syscall convention. We do not
1121 bother converting structures between the two
1122 ABIs, but basic functionality should work even
1123 if strace and the traced program have different
1124 ABIs. */
1125 if (scno == 0xef000000) {
1126 scno = regs.ARM_r7;
1127 } else {
1128 if ((scno & 0x0ff00000) != 0x0f900000) {
1129 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1130 scno);
1131 return -1;
1132 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001133
Roland McGrathf691bd22006-04-25 07:34:41 +00001134 /*
1135 * Fixup the syscall number
1136 */
1137 scno &= 0x000fffff;
1138 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001139 }
Roland McGrath56703312008-05-20 01:35:55 +00001140 if (scno & 0x0f0000) {
1141 /*
1142 * Handle ARM specific syscall
1143 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001144 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +00001145 scno &= 0x0000ffff;
1146 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001147 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001148
Roland McGrath0f87c492003-06-03 23:29:04 +00001149 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001150 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1151 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001152 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001153#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001154 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001155 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001156#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001157 unsigned long long regs[38];
1158
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001159 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001160 return -1;
1161 a3 = regs[REG_A3];
1162 r2 = regs[REG_V0];
1163
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001164 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001165 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001166 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001167 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001168 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001169 return 0;
1170 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001171 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001172#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001173 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001174 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001175 if (upeek(tcp, REG_V0, &scno) < 0)
1176 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001177
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001178 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001179 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001180 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001181 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001182 return 0;
1183 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001184 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001185#elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001186 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001187 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001188 if (upeek(tcp, REG_R0, &scno) < 0)
1189 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001190
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001191 /*
1192 * Do some sanity checks to figure out if it's
1193 * really a syscall entry
1194 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001195 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001196 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001197 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001198 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001199 return 0;
1200 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001201 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001202#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001203 /* Disassemble the syscall trap. */
1204 /* Retrieve the syscall trap instruction. */
1205 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001206# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001207 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1208 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001209# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001210 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001211# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001212 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001213 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001214
1215 /* Disassemble the trap to see what personality to use. */
1216 switch (trap) {
1217 case 0x91d02010:
1218 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001219 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001220 break;
1221 case 0x91d0206d:
1222 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001223 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001224 break;
1225 case 0x91d02000:
1226 /* SunOS syscall trap. (pers 1) */
1227 fprintf(stderr, "syscall: SunOS no support\n");
1228 return -1;
1229 case 0x91d02008:
1230 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001231 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001232 break;
1233 case 0x91d02009:
1234 /* NetBSD/FreeBSD syscall trap. */
1235 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1236 return -1;
1237 case 0x91d02027:
1238 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001239 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001240 break;
1241 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001242# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001243 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001244# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001245 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001246# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001247 return -1;
1248 }
1249
1250 /* Extract the system call number from the registers. */
1251 if (trap == 0x91d02027)
1252 scno = 156;
1253 else
1254 scno = regs.u_regs[U_REG_G1];
1255 if (scno == 0) {
1256 scno = regs.u_regs[U_REG_O0];
1257 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1258 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001259#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001260 if (upeek(tcp, PT_GR20, &scno) < 0)
1261 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001262#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001263 /*
1264 * In the new syscall ABI, the system call number is in R3.
1265 */
1266 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1267 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001268
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001269 if (scno < 0) {
1270 /* Odd as it may seem, a glibc bug has been known to cause
1271 glibc to issue bogus negative syscall numbers. So for
1272 our purposes, make strace print what it *should* have been */
1273 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001274 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001275 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001276 "Detected glibc bug: bogus system call"
1277 " number = %ld, correcting to %ld\n",
1278 scno,
1279 correct_scno);
1280 scno = correct_scno;
1281 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001282#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001283 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001284 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001285 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001286#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001287 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1288 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001289#elif defined(TILE)
Chris Metcalfc8c66982009-12-28 10:00:15 -05001290 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1291 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001292#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001293 if (upeek(tcp, 0, &scno) < 0)
1294 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001295#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001296
Denys Vlasenko523635f2012-02-25 02:44:25 +01001297#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001298 /* new syscall ABI returns result in R0 */
1299 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1300 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001301#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001302 /* ABI defines result returned in r9 */
1303 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1304 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001305#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001306
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001307 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001308 return 1;
1309}
1310
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001311/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001312 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001313 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1314 * 1: ok, continue in trace_syscall_entering().
1315 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001316 * ("????" etc) and bail out.
1317 */
Roland McGratha4d48532005-06-08 20:45:28 +00001318static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001319syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001320{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001321 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001322#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001323 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001324 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001325 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1326 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001327 }
H.J. Lu35be5812012-04-16 13:00:01 +02001328#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001329 {
1330 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001331 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001332 rax = (int)rax; /* sign extend from 32 bits */
1333 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001334 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001335 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1336 return 0;
1337 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001338 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001339#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001340 /* TODO: we already fetched PT_GPR2 in get_scno
1341 * and stored it in syscall_mode, reuse it here
1342 * instead of re-fetching?
1343 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001344 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001345 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001346 if (syscall_mode != -ENOSYS)
1347 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001348 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001349 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001350 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001351 return 0;
1352 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001353#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001354 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001355 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001356 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001357 if (d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001358 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001359 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001360 return 0;
1361 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001362#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001363 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001364 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001365 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001366 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001367 if (ia32 && r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001368 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001369 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001370 return 0;
1371 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001372#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001373 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001374 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001375 if (r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001376 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001377 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001378 return 0;
1379 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001380#elif defined(MICROBLAZE)
1381 if (upeek(tcp, 3 * 4, &r3) < 0)
1382 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001383 if (r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001384 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001385 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001386 return 0;
1387 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001388#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001389 return 1;
1390}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001391
Denys Vlasenko146b9442012-03-18 22:10:48 +01001392static void
1393internal_fork(struct tcb *tcp)
1394{
1395#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1396# define ARG_FLAGS 1
1397#else
1398# define ARG_FLAGS 0
1399#endif
1400#ifndef CLONE_UNTRACED
1401# define CLONE_UNTRACED 0x00800000
1402#endif
1403 if ((ptrace_setoptions
1404 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1405 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1406 return;
1407
1408 if (!followfork)
1409 return;
1410
1411 if (entering(tcp)) {
1412 /*
1413 * We won't see the new child if clone is called with
1414 * CLONE_UNTRACED, so we keep the same logic with that option
1415 * and don't trace it.
1416 */
1417 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1418 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1419 return;
1420 setbpt(tcp);
1421 } else {
1422 if (tcp->flags & TCB_BPTSET)
1423 clearbpt(tcp);
1424 }
1425}
1426
1427#if defined(TCB_WAITEXECVE)
1428static void
1429internal_exec(struct tcb *tcp)
1430{
1431 /* Maybe we have post-execve SIGTRAP suppressed? */
1432 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1433 return; /* yes, no need to do anything */
1434
1435 if (exiting(tcp) && syserror(tcp))
1436 /* Error in execve, no post-execve SIGTRAP expected */
1437 tcp->flags &= ~TCB_WAITEXECVE;
1438 else
1439 tcp->flags |= TCB_WAITEXECVE;
1440}
1441#endif
1442
1443static void
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001444internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001445{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001446 /*
1447 * We must always trace a few critical system calls in order to
1448 * correctly support following forks in the presence of tracing
1449 * qualifiers.
1450 */
1451 int (*func)();
1452
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001453 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001454 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001455
1456 func = sysent[tcp->scno].sys_func;
1457
1458 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001459 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001460 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001461 ) {
1462 internal_fork(tcp);
1463 return;
1464 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001465
Denys Vlasenko84703742012-02-25 02:38:52 +01001466#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001467 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001468# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001469 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001470# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001471 ) {
1472 internal_exec(tcp);
1473 return;
1474 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001475#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001476}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001477
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001478/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001479static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001480get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001481{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001482 int i, nargs;
1483
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001484 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001485 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001486 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001487 nargs = tcp->u_nargs = MAX_ARGS;
1488
Denys Vlasenko523635f2012-02-25 02:44:25 +01001489#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001490 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001491 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1492 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001493#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001494 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001495 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1496 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001497#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001498 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001499 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001500 long rbs_end;
1501 /* be backwards compatible with kernel < 2.4.4... */
1502# ifndef PT_RBS_END
1503# define PT_RBS_END PT_AR_BSP
1504# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001505
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001506 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1507 return -1;
1508 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001509 return -1;
1510
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001511 sof = (cfm >> 0) & 0x7f;
1512 sol = (cfm >> 7) & 0x7f;
1513 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1514
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001515 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001516 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1517 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1518 return -1;
1519 }
1520 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001521 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1522 PT_R9 /* ECX = out1 */,
1523 PT_R10 /* EDX = out2 */,
1524 PT_R14 /* ESI = out3 */,
1525 PT_R15 /* EDI = out4 */,
1526 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001527
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001528 for (i = 0; i < nargs; ++i) {
1529 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1530 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001531 /* truncate away IVE sign-extension */
1532 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001533 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001534 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001535#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001536 /* N32 and N64 both use up to six registers. */
1537 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001538
1539 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1540 return -1;
1541
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001542 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001543 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001544# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001545 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001546# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001547 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001548#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001549 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001550 long sp;
1551
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001552 if (upeek(tcp, REG_SP, &sp) < 0)
1553 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001554 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001555 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1556 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001557 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001558 (char *)(tcp->u_arg + 4));
1559 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001560 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001561 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001562 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001563 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001564#elif defined(POWERPC)
1565# ifndef PT_ORIG_R3
1566# define PT_ORIG_R3 34
1567# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001568 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001569 if (upeek(tcp, (i==0) ?
1570 (sizeof(unsigned long) * PT_ORIG_R3) :
1571 ((i+PT_R3) * sizeof(unsigned long)),
1572 &tcp->u_arg[i]) < 0)
1573 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001574 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001575#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001576 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001577 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001578#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001579 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001580 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1581 return -1;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001582#elif defined(ARM) || defined(AARCH64)
1583# if defined(AARCH64)
1584 if (tcp->currpers == 1)
1585 for (i = 0; i < nargs; ++i)
1586 tcp->u_arg[i] = aarch64_regs.regs[i];
1587 else
1588# endif /* AARCH64 */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001589 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001590 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001591#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001592 (void)i;
1593 (void)nargs;
1594 tcp->u_arg[0] = regs.r12;
1595 tcp->u_arg[1] = regs.r11;
1596 tcp->u_arg[2] = regs.r10;
1597 tcp->u_arg[3] = regs.r9;
1598 tcp->u_arg[4] = regs.r5;
1599 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001600#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001601 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 +02001602
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001603 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001604 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1605 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001606#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001607 static const int syscall_regs[MAX_ARGS] = {
1608 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1609 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001610 };
1611
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001612 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001613 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001614 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001615#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001616 int i;
1617 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001618 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001619
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001620 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001621 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1622 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001623#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001624 (void)i;
1625 (void)nargs;
H.J. Lu35be5812012-04-16 13:00:01 +02001626 if (current_personality != 1) { /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001627 tcp->u_arg[0] = x86_64_regs.rdi;
1628 tcp->u_arg[1] = x86_64_regs.rsi;
1629 tcp->u_arg[2] = x86_64_regs.rdx;
1630 tcp->u_arg[3] = x86_64_regs.r10;
1631 tcp->u_arg[4] = x86_64_regs.r8;
1632 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001633# ifdef X32
1634 tcp->ext_arg[0] = x86_64_regs.rdi;
1635 tcp->ext_arg[1] = x86_64_regs.rsi;
1636 tcp->ext_arg[2] = x86_64_regs.rdx;
1637 tcp->ext_arg[3] = x86_64_regs.r10;
1638 tcp->ext_arg[4] = x86_64_regs.r8;
1639 tcp->ext_arg[5] = x86_64_regs.r9;
1640# endif
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001641 } else { /* i386 ABI */
1642 /* Sign-extend lower 32 bits */
1643 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1644 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1645 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1646 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1647 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1648 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1649 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001650#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001651 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001652 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1653 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001654#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001655 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001656 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001657 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001658 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001659
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001660 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001661 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1662 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001663#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001664 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001665 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1666 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001667#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001668 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001669 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1670 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001671#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001672 (void)i;
1673 (void)nargs;
1674 tcp->u_arg[0] = i386_regs.ebx;
1675 tcp->u_arg[1] = i386_regs.ecx;
1676 tcp->u_arg[2] = i386_regs.edx;
1677 tcp->u_arg[3] = i386_regs.esi;
1678 tcp->u_arg[4] = i386_regs.edi;
1679 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001680#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001681 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001682 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1683 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001684#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001685 return 1;
1686}
1687
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001688static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001689trace_syscall_entering(struct tcb *tcp)
1690{
1691 int res, scno_good;
1692
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001693#if defined TCB_WAITEXECVE
1694 if (tcp->flags & TCB_WAITEXECVE) {
1695 /* This is the post-execve SIGTRAP. */
1696 tcp->flags &= ~TCB_WAITEXECVE;
1697 return 0;
1698 }
1699#endif
1700
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001701 scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001702 if (res == 0)
1703 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001704 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001705 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001706 if (res == 0)
1707 return res;
1708 if (res == 1)
1709 res = get_syscall_args(tcp);
1710 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001711
1712 if (res != 1) {
1713 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001714 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001715 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001716 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001717 tprintf("syscall_%lu(", tcp->scno);
1718 else
1719 tprintf("%s(", sysent[tcp->scno].sys_name);
1720 /*
1721 * " <unavailable>" will be added later by the code which
1722 * detects ptrace errors.
1723 */
1724 goto ret;
1725 }
1726
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001727#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1728 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001729# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001730 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001731 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001732 break;
1733 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001734# endif
1735# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001736 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001737 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001738 break;
1739 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001740# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001741 break;
1742 }
1743#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1744
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001745 internal_syscall(tcp);
1746
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001747 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001748 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1749 (tracing_paths && !pathtrace_match(tcp))) {
1750 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1751 return 0;
1752 }
1753
1754 tcp->flags &= ~TCB_FILTERED;
1755
1756 if (cflag == CFLAG_ONLY_STATS) {
1757 res = 0;
1758 goto ret;
1759 }
1760
1761 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001762 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001763 tprintf("syscall_%lu(", tcp->scno);
1764 else
1765 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001766 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001767 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1768 sysent[tcp->scno].sys_func != sys_exit))
1769 res = printargs(tcp);
1770 else
1771 res = (*sysent[tcp->scno].sys_func)(tcp);
1772
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001773 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001774 ret:
1775 tcp->flags |= TCB_INSYSCALL;
1776 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001777 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001778 gettimeofday(&tcp->etime, NULL);
1779 return res;
1780}
1781
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001782/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001783 * 1: ok, continue in trace_syscall_exiting().
1784 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001785 * ("????" etc) and bail out.
1786 */
1787static int
1788get_syscall_result(struct tcb *tcp)
1789{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001790#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001791 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1792 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001793#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001794# define SO_MASK 0x10000000
1795 {
1796 long flags;
1797 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1798 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001799 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001800 return -1;
1801 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001802 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001803 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001804#elif defined(AVR32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001805 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001806#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001807 if (upeek(tcp, PT_R0, &r0) < 0)
1808 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001809#elif defined(I386)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001810 /* already done by get_regs */
H.J. Lu35be5812012-04-16 13:00:01 +02001811#elif defined(X86_64) || defined(X32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001812 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001813#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001814# define IA64_PSR_IS ((long)1 << 34)
1815 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1816 ia32 = (psr & IA64_PSR_IS) != 0;
1817 if (upeek(tcp, PT_R8, &r8) < 0)
1818 return -1;
1819 if (upeek(tcp, PT_R10, &r10) < 0)
1820 return -1;
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001821#elif defined(AARCH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001822/* FIXME: uh, why do we do it on syscall *exit*? We did it on entry already... */
1823 /* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
1824 * else it's personality 0.
1825 */
1826 update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001827#elif defined(ARM)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001828 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001829#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001830 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1831 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001832#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001833 unsigned long long regs[38];
1834
1835 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1836 return -1;
1837 a3 = regs[REG_A3];
1838 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001839#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001840 if (upeek(tcp, REG_A3, &a3) < 0)
1841 return -1;
1842 if (upeek(tcp, REG_V0, &r2) < 0)
1843 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001844#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001845 if (upeek(tcp, REG_A3, &a3) < 0)
1846 return -1;
1847 if (upeek(tcp, REG_R0, &r0) < 0)
1848 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001849#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001850 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001851#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001852 if (upeek(tcp, PT_GR28, &r28) < 0)
1853 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001854#elif defined(SH)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001855 /* new syscall ABI returns result in R0 */
1856 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1857 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001858#elif defined(SH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001859 /* ABI defines result returned in r9 */
1860 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1861 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001862#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001863 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1864 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001865#elif defined(TILE)
1866#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001867 if (upeek(tcp, 3 * 4, &r3) < 0)
1868 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001869#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001870 return 1;
1871}
1872
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001873/* Called at each syscall exit */
1874static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001875syscall_fixup_on_sysexit(struct tcb *tcp)
1876{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001877#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001878 if (syscall_mode != -ENOSYS)
1879 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001880 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001881 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1882 /*
1883 * Return from execve.
1884 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1885 * flag set for the post-execve SIGTRAP to see and reset.
1886 */
1887 gpr2 = 0;
1888 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001889#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001890}
1891
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001892/*
1893 * Check the syscall return value register value for whether it is
1894 * a negated errno code indicating an error, or a success return value.
1895 */
1896static inline int
1897is_negated_errno(unsigned long int val)
1898{
1899 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001900#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001901 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001902 val = (unsigned int) val;
1903 max = (unsigned int) max;
1904 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001905#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001906 return val > max;
1907}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001908
Denys Vlasenko907735a2012-03-21 00:23:16 +01001909/* Returns:
1910 * 1: ok, continue in trace_syscall_exiting().
1911 * -1: error, trace_syscall_exiting() should print error indicator
1912 * ("????" etc) and bail out.
1913 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001914static int
1915get_error(struct tcb *tcp)
1916{
1917 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001918 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001919 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001920 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1921 check_errno = 0;
1922 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001923#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001924 if (check_errno && is_negated_errno(gpr2)) {
1925 tcp->u_rval = -1;
1926 u_error = -gpr2;
1927 }
1928 else {
1929 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001930 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001931#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001932 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001933 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001934 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001935 }
1936 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001937 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001938 }
H.J. Lu35be5812012-04-16 13:00:01 +02001939#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001940 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001941 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001942 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001943 }
1944 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001945 tcp->u_rval = x86_64_regs.rax;
H.J. Lu35be5812012-04-16 13:00:01 +02001946# if defined(X32)
1947 tcp->u_lrval = x86_64_regs.rax;
1948# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001949 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001950#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001951 if (ia32) {
1952 int err;
1953
1954 err = (int)r8;
1955 if (check_errno && is_negated_errno(err)) {
1956 tcp->u_rval = -1;
1957 u_error = -err;
1958 }
1959 else {
1960 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001961 }
1962 } else {
1963 if (check_errno && r10) {
1964 tcp->u_rval = -1;
1965 u_error = r8;
1966 } else {
1967 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001968 }
1969 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001970#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001971 if (check_errno && a3) {
1972 tcp->u_rval = -1;
1973 u_error = r2;
1974 } else {
1975 tcp->u_rval = r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02001976# if defined(LINUX_MIPSN32)
1977 tcp->u_lrval = r2;
1978# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001979 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001980#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001981 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001982 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001983 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001984 }
1985 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001986 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001987 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001988#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001989 if (check_errno && is_negated_errno(d0)) {
1990 tcp->u_rval = -1;
1991 u_error = -d0;
1992 }
1993 else {
1994 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001995 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001996#elif defined(ARM) || defined(AARCH64)
1997# if defined(AARCH64)
1998 if (tcp->currpers == 1) {
1999 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2000 tcp->u_rval = -1;
2001 u_error = -aarch64_regs.regs[0];
2002 }
2003 else {
2004 tcp->u_rval = aarch64_regs.regs[0];
2005 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002006 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002007 else
2008# endif /* AARCH64 */
2009 {
2010 if (check_errno && is_negated_errno(regs.ARM_r0)) {
2011 tcp->u_rval = -1;
2012 u_error = -regs.ARM_r0;
2013 }
2014 else {
2015 tcp->u_rval = regs.ARM_r0;
2016 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002017 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002018#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002019 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
2020 tcp->u_rval = -1;
2021 u_error = -regs.r12;
2022 }
2023 else {
2024 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002025 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002026#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002027 if (check_errno && is_negated_errno(r0)) {
2028 tcp->u_rval = -1;
2029 u_error = -r0;
2030 } else {
2031 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002032 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002033#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002034 if (check_errno && a3) {
2035 tcp->u_rval = -1;
2036 u_error = r0;
2037 }
2038 else {
2039 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002040 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002041#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002042 if (check_errno && regs.psr & PSR_C) {
2043 tcp->u_rval = -1;
2044 u_error = regs.u_regs[U_REG_O0];
2045 }
2046 else {
2047 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002048 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002049#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002050 if (check_errno && regs.tstate & 0x1100000000UL) {
2051 tcp->u_rval = -1;
2052 u_error = regs.u_regs[U_REG_O0];
2053 }
2054 else {
2055 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002056 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002057#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002058 if (check_errno && is_negated_errno(r28)) {
2059 tcp->u_rval = -1;
2060 u_error = -r28;
2061 }
2062 else {
2063 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002064 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002065#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002066 if (check_errno && is_negated_errno(r0)) {
2067 tcp->u_rval = -1;
2068 u_error = -r0;
2069 }
2070 else {
2071 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002072 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002073#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002074 if (check_errno && is_negated_errno(r9)) {
2075 tcp->u_rval = -1;
2076 u_error = -r9;
2077 }
2078 else {
2079 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002080 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002081#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002082 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
2083 tcp->u_rval = -1;
2084 u_error = -r10;
2085 }
2086 else {
2087 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002088 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002089#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002090 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002091 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
2092 return -1;
2093 if (check_errno && rval < 0 && rval > -nerrnos) {
2094 tcp->u_rval = -1;
2095 u_error = -rval;
2096 }
2097 else {
2098 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002099 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002100#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002101 if (check_errno && is_negated_errno(r3)) {
2102 tcp->u_rval = -1;
2103 u_error = -r3;
2104 }
2105 else {
2106 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002107 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002108#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002109 tcp->u_error = u_error;
2110 return 1;
2111}
2112
2113static void
2114dumpio(struct tcb *tcp)
2115{
2116 if (syserror(tcp))
2117 return;
2118 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
2119 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002120 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002121 return;
2122 if (sysent[tcp->scno].sys_func == printargs)
2123 return;
2124 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
2125 if (sysent[tcp->scno].sys_func == sys_read ||
2126 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002127 sysent[tcp->scno].sys_func == sys_recv ||
2128 sysent[tcp->scno].sys_func == sys_recvfrom)
2129 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
2130 else if (sysent[tcp->scno].sys_func == sys_readv)
2131 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2132 return;
2133 }
2134 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
2135 if (sysent[tcp->scno].sys_func == sys_write ||
2136 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002137 sysent[tcp->scno].sys_func == sys_send ||
2138 sysent[tcp->scno].sys_func == sys_sendto)
2139 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
2140 else if (sysent[tcp->scno].sys_func == sys_writev)
2141 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2142 return;
2143 }
2144}
2145
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002146static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002147trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002148{
2149 int sys_res;
2150 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002151 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002152 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002153
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002154 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002155 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002156 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002157
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002158#if SUPPORTED_PERSONALITIES > 1
2159 update_personality(tcp, tcp->currpers);
2160#endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002161 res = (get_regs_error ? -1 : get_syscall_result(tcp));
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002162 if (res == 1) {
2163 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01002164 res = get_error(tcp); /* returns 1 or -1 */
2165 if (res == 1) {
2166 internal_syscall(tcp);
2167 if (filtered(tcp)) {
2168 goto ret;
2169 }
2170 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002171 }
2172
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002173 if (cflag) {
2174 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002175 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002176 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002177 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002178 }
2179 }
2180
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002181 /* If not in -ff mode, and printing_tcp != tcp,
2182 * then the log currently does not end with output
2183 * of _our syscall entry_, but with something else.
2184 * We need to say which syscall's return is this.
2185 *
2186 * Forced reprinting via TCB_REPRINT is used only by
2187 * "strace -ff -oLOG test/threaded_execve" corner case.
2188 * It's the only case when -ff mode needs reprinting.
2189 */
2190 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2191 tcp->flags &= ~TCB_REPRINT;
2192 printleader(tcp);
2193 if (!SCNO_IN_RANGE(tcp->scno))
2194 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2195 else
2196 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2197 }
2198 printing_tcp = tcp;
2199
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002200 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002201 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002202 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002203 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002204 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002205 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002206 tcp->flags &= ~TCB_INSYSCALL;
2207 return res;
2208 }
2209
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002210 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002211 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002212 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002213 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002214 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002215 /* FIXME: not_failing_only (IOW, option -z) is broken:
2216 * failure of syscall is known only after syscall return.
2217 * Thus we end up with something like this on, say, ENOENT:
2218 * open("doesnt_exist", O_RDONLY <unfinished ...>
2219 * {next syscall decode}
2220 * whereas the intended result is that open(...) line
2221 * is not shown at all.
2222 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002223 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002224 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002225 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2226 }
2227
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002228 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002229 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002230 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002231 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002232 qual_flags[tcp->scno] & QUAL_RAW) {
2233 if (u_error)
2234 tprintf("= -1 (errno %ld)", u_error);
2235 else
2236 tprintf("= %#lx", tcp->u_rval);
2237 }
2238 else if (!(sys_res & RVAL_NONE) && u_error) {
2239 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002240 /* Blocked signals do not interrupt any syscalls.
2241 * In this case syscalls don't return ERESTARTfoo codes.
2242 *
2243 * Deadly signals set to SIG_DFL interrupt syscalls
2244 * and kill the process regardless of which of the codes below
2245 * is returned by the interrupted syscall.
2246 * In some cases, kernel forces a kernel-generated deadly
2247 * signal to be unblocked and set to SIG_DFL (and thus cause
2248 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2249 * or SIGILL. (The alternative is to leave process spinning
2250 * forever on the faulty instruction - not useful).
2251 *
2252 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2253 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2254 * but kernel will always restart them.
2255 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002256 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002257 /* Most common type of signal-interrupted syscall exit code.
2258 * The system call will be restarted with the same arguments
2259 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2260 */
2261 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002262 break;
2263 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002264 /* Rare. For example, fork() returns this if interrupted.
2265 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2266 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002267 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002268 break;
2269 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002270 /* pause(), rt_sigsuspend() etc use this code.
2271 * SA_RESTART is ignored (assumed not set):
2272 * syscall won't restart (will return EINTR instead)
2273 * even after signal with SA_RESTART set.
2274 * However, after SIG_IGN or SIG_DFL signal it will.
2275 */
2276 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002277 break;
2278 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002279 /* Syscalls like nanosleep(), poll() which can't be
2280 * restarted with their original arguments use this
2281 * code. Kernel will execute restart_syscall() instead,
2282 * which changes arguments before restarting syscall.
2283 * SA_RESTART is ignored (assumed not set) similarly
2284 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2285 * since restart data is saved in "restart block"
2286 * in task struct, and if signal handler uses a syscall
2287 * which in turn saves another such restart block,
2288 * old data is lost and restart becomes impossible)
2289 */
2290 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002291 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002292 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002293 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002294 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002295 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002296 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002297 strerror(u_error));
2298 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002299 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002300 strerror(u_error));
2301 break;
2302 }
2303 if ((sys_res & RVAL_STR) && tcp->auxstr)
2304 tprintf(" (%s)", tcp->auxstr);
2305 }
2306 else {
2307 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002308 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002309 else {
2310 switch (sys_res & RVAL_MASK) {
2311 case RVAL_HEX:
2312 tprintf("= %#lx", tcp->u_rval);
2313 break;
2314 case RVAL_OCTAL:
2315 tprintf("= %#lo", tcp->u_rval);
2316 break;
2317 case RVAL_UDECIMAL:
2318 tprintf("= %lu", tcp->u_rval);
2319 break;
2320 case RVAL_DECIMAL:
2321 tprintf("= %ld", tcp->u_rval);
2322 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002323#if defined(LINUX_MIPSN32) || defined(X32)
2324 /*
2325 case RVAL_LHEX:
2326 tprintf("= %#llx", tcp->u_lrval);
2327 break;
2328 case RVAL_LOCTAL:
2329 tprintf("= %#llo", tcp->u_lrval);
2330 break;
2331 */
2332 case RVAL_LUDECIMAL:
2333 tprintf("= %llu", tcp->u_lrval);
2334 break;
2335 /*
2336 case RVAL_LDECIMAL:
2337 tprintf("= %lld", tcp->u_lrval);
2338 break;
2339 */
2340#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002341 default:
2342 fprintf(stderr,
2343 "invalid rval format\n");
2344 break;
2345 }
2346 }
2347 if ((sys_res & RVAL_STR) && tcp->auxstr)
2348 tprintf(" (%s)", tcp->auxstr);
2349 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002350 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002351 tv_sub(&tv, &tv, &tcp->etime);
2352 tprintf(" <%ld.%06ld>",
2353 (long) tv.tv_sec, (long) tv.tv_usec);
2354 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002355 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002356 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002357 line_ended();
2358
Denys Vlasenko3b738812011-08-22 02:06:35 +02002359 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002360 tcp->flags &= ~TCB_INSYSCALL;
2361 return 0;
2362}
2363
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002364int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002365trace_syscall(struct tcb *tcp)
2366{
2367 return exiting(tcp) ?
2368 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2369}