blob: 3efb02415235bd922fc1b1ad3b0a680cd2227b91 [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 Vlasenko1ebe08d2013-02-05 16:55:23 +0100615#if defined(SPARC) || defined(SPARC64) || defined(IA64) || defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200616long
617getrval2(struct tcb *tcp)
618{
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100619 long val;
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200620
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100621# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200622 val = regs.u_regs[U_REG_O1];
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100623# elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200624 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
625 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100626# elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200627 if (upeek(tcp, PT_R9, &val) < 0)
628 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100629# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200630
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200631 return val;
632}
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100633#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200634
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200635int
636is_restart_error(struct tcb *tcp)
637{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200638 switch (tcp->u_error) {
639 case ERESTARTSYS:
640 case ERESTARTNOINTR:
641 case ERESTARTNOHAND:
642 case ERESTART_RESTARTBLOCK:
643 return 1;
644 default:
645 break;
646 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200647 return 0;
648}
649
Denys Vlasenko523635f2012-02-25 02:44:25 +0100650#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100651struct pt_regs i386_regs;
H.J. Lu35be5812012-04-16 13:00:01 +0200652#elif defined(X86_64) || defined(X32)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100653/*
654 * On 32 bits, pt_regs and user_regs_struct are the same,
655 * but on 64 bits, user_regs_struct has six more fields:
656 * fs_base, gs_base, ds, es, fs, gs.
657 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
658 */
659static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100660#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200661long r8, r10, psr; /* TODO: make static? */
662long ia32 = 0; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100663#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +0100664static long ppc_result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100665#elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200666static long d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100667#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200668static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100669#elif defined(ARM)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100670struct pt_regs regs; /* not static */
Steve McIntyred8d3bd32012-10-24 17:58:16 +0100671#elif defined(AARCH64)
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000672static struct user_pt_regs aarch64_regs;
673static struct arm_pt_regs regs;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100674static struct iovec aarch64_io = {
675 .iov_base = &aarch64_regs
676};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100677#elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200678static long r0;
679static long a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100680#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200681static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100682#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100683struct pt_regs regs; /* not static */
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200684static unsigned long trap;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100685#elif defined(LINUX_MIPSN32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200686static long long a3;
687static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100688#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200689static long a3;
690static long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100691#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200692static long gpr2;
693static long pc;
694static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100695#elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200696static long r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100697#elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200698static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100699#elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200700static long r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100701#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200702static long r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100703#elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200704static long r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100705#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000706
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100707void
708printcall(struct tcb *tcp)
709{
710#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
711 sizeof(long) == 8 ? "[????????????????] " : \
712 NULL /* crash */)
713 if (get_regs_error) {
714 PRINTBADPC;
715 return;
716 }
717#if defined(I386)
718 tprintf("[%08lx] ", i386_regs.eip);
719#elif defined(S390) || defined(S390X)
720 long psw;
721 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
722 PRINTBADPC;
723 return;
724 }
725# ifdef S390
726 tprintf("[%08lx] ", psw);
727# elif S390X
728 tprintf("[%16lx] ", psw);
729# endif
730#elif defined(X86_64) || defined(X32)
731 tprintf("[%16lx] ", x86_64_regs.ip);
732#elif defined(IA64)
733 long ip;
734
735 if (upeek(tcp, PT_B0, &ip) < 0) {
736 PRINTBADPC;
737 return;
738 }
739 tprintf("[%08lx] ", ip);
740#elif defined(POWERPC)
741 long pc;
742
743 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
744 PRINTBADPC;
745 return;
746 }
747# ifdef POWERPC64
748 tprintf("[%016lx] ", pc);
749# else
750 tprintf("[%08lx] ", pc);
751# endif
752#elif defined(M68K)
753 long pc;
754
755 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
756 tprints("[????????] ");
757 return;
758 }
759 tprintf("[%08lx] ", pc);
760#elif defined(ALPHA)
761 long pc;
762
763 if (upeek(tcp, REG_PC, &pc) < 0) {
764 tprints("[????????????????] ");
765 return;
766 }
767 tprintf("[%08lx] ", pc);
768#elif defined(SPARC)
769 tprintf("[%08lx] ", regs.pc);
770#elif defined(SPARC64)
771 tprintf("[%08lx] ", regs.tpc);
772#elif defined(HPPA)
773 long pc;
774
775 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
776 tprints("[????????] ");
777 return;
778 }
779 tprintf("[%08lx] ", pc);
780#elif defined(MIPS)
781 long pc;
782
783 if (upeek(tcp, REG_EPC, &pc) < 0) {
784 tprints("[????????] ");
785 return;
786 }
787 tprintf("[%08lx] ", pc);
788#elif defined(SH)
789 long pc;
790
791 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
792 tprints("[????????] ");
793 return;
794 }
795 tprintf("[%08lx] ", pc);
796#elif defined(SH64)
797 long pc;
798
799 if (upeek(tcp, REG_PC, &pc) < 0) {
800 tprints("[????????????????] ");
801 return;
802 }
803 tprintf("[%08lx] ", pc);
804#elif defined(ARM)
805 tprintf("[%08lx] ", regs.ARM_pc);
806/*#elif defined(AARCH64) ??? */
807#elif defined(AVR32)
808 tprintf("[%08lx] ", regs.pc);
809#elif defined(BFIN)
810 long pc;
811
812 if (upeek(tcp, PT_PC, &pc) < 0) {
813 PRINTBADPC;
814 return;
815 }
816 tprintf("[%08lx] ", pc);
817#elif defined(CRISV10)
818 long pc;
819
820 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
821 PRINTBADPC;
822 return;
823 }
824 tprintf("[%08lx] ", pc);
825#elif defined(CRISV32)
826 long pc;
827
828 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
829 PRINTBADPC;
830 return;
831 }
832 tprintf("[%08lx] ", pc);
833#endif /* architecture */
834}
835
836#ifndef get_regs
837long get_regs_error;
838void get_regs(pid_t pid)
839{
840# if defined(AVR32)
841 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
842# elif defined(I386)
843 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &i386_regs);
844# elif defined(X86_64) || defined(X32)
845 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &x86_64_regs);
846# elif defined(AARCH64)
847 /*aarch64_io.iov_base = &aarch64_regs; - already is */
848 aarch64_io.iov_len = sizeof(aarch64_regs);
849 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void *)&aarch64_io);
850 if (get_regs_error)
851 return;
852 switch (aarch64_io.iov_len) {
853 case sizeof(regs):
854 /* We are in 32-bit mode */
855 memcpy(&regs, &aarch64_regs, sizeof(regs));
856 break;
857 case sizeof(aarch64_regs):
858 /* We are in 64-bit mode */
859 /* Data is already in aarch64_regs */
860 break;
861 default:
862 get_regs_error = -1;
863 break;
864 }
865# elif defined(ARM)
866 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (void *)&regs);
867# elif defined(SPARC) || defined(SPARC64)
868 get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&regs, 0);
869# endif
870}
871#endif
872
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200873/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100874 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
875 * 1: ok, continue in trace_syscall_entering().
876 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200877 * ("????" etc) and bail out.
878 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100879static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200880get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000881{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000882 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000883
Denys Vlasenko523635f2012-02-25 02:44:25 +0100884#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000885 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200886 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000887
888 if (syscall_mode != -ENOSYS) {
889 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000890 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000891 */
892 scno = syscall_mode;
893 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000894 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000895 * Old style of "passing" the scno via the SVC instruction.
896 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000897 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200898 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200899 static const int gpr_offset[16] = {
900 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
901 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
902 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
903 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
904 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000905
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000906 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000907 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000908 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000909 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000910 if (errno) {
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000911 perror_msg("%s", "peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000912 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000913 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000914
915 /*
916 * We have to check if the SVC got executed directly or via an
917 * EXECUTE instruction. In case of EXECUTE it is necessary to do
918 * instruction decoding to derive the system call number.
919 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
920 * so that this doesn't work if a SVC opcode is part of an EXECUTE
921 * opcode. Since there is no way to find out the opcode size this
922 * is the best we can do...
923 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000924 if ((opcode & 0xff00) == 0x0a00) {
925 /* SVC opcode */
926 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000927 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000928 else {
929 /* SVC got executed by EXECUTE instruction */
930
931 /*
932 * Do instruction decoding of EXECUTE. If you really want to
933 * understand this, read the Principles of Operations.
934 */
935 svc_addr = (void *) (opcode & 0xfff);
936
937 tmp = 0;
938 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000939 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000940 return -1;
941 svc_addr += tmp;
942
943 tmp = 0;
944 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000945 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000946 return -1;
947 svc_addr += tmp;
948
Denys Vlasenkofb036672009-01-23 16:30:26 +0000949 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000950 if (errno)
951 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100952# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000953 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100954# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000955 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100956# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000957 tmp = 0;
958 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000959 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000960 return -1;
961
962 scno = (scno | tmp) & 0xff;
963 }
964 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100965#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000966 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000967 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100968# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200969 /* TODO: speed up strace by not doing this at every syscall.
970 * We only need to do it after execve.
971 */
972 int currpers;
973 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200974
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200975 /* Check for 64/32 bit mode. */
976 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
977 return -1;
978 /* SF is bit 0 of MSR */
979 if (val < 0)
980 currpers = 0;
981 else
982 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000983 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100984# endif
985#elif defined(AVR32)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200986 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100987#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000988 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000989 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100990#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200991 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +0200992#elif defined(X86_64) || defined(X32)
993# ifndef __X32_SYSCALL_BIT
994# define __X32_SYSCALL_BIT 0x40000000
995# endif
996# ifndef __X32_SYSCALL_MASK
997# define __X32_SYSCALL_MASK __X32_SYSCALL_BIT
998# endif
999
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001000 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001001 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +00001002
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001003 /* Check CS register value. On x86-64 linux it is:
1004 * 0x33 for long mode (64 bit)
1005 * 0x23 for compatibility mode (32 bit)
H.J. Lu35be5812012-04-16 13:00:01 +02001006 * Check DS register value. On x86-64 linux it is:
1007 * 0x2b for x32 mode (x86-64 in 32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001008 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001009 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001010 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +02001011 case 0x33:
1012 if (x86_64_regs.ds == 0x2b) {
1013 currpers = 2;
1014 scno &= ~__X32_SYSCALL_MASK;
1015 } else
1016 currpers = 0;
1017 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001018 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001019 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001020 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001021 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001022 currpers = current_personality;
1023 break;
1024 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001025# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001026 /* This version analyzes the opcode of a syscall instruction.
1027 * (int 0x80 on i386 vs. syscall on x86-64)
1028 * It works, but is too complicated.
1029 */
1030 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +00001031
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001032 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +00001033
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001034 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
1035 rip -= 2;
1036 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +00001037
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001038 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001039 if (errno)
1040 fprintf(stderr, "ptrace_peektext failed: %s\n",
1041 strerror(errno));
1042 switch (call & 0xffff) {
1043 /* x86-64: syscall = 0x0f 0x05 */
1044 case 0x050f: currpers = 0; break;
1045 /* i386: int 0x80 = 0xcd 0x80 */
1046 case 0x80cd: currpers = 1; break;
1047 default:
1048 currpers = current_personality;
1049 fprintf(stderr,
1050 "Unknown syscall opcode (0x%04X) while "
1051 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001052 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001053 break;
1054 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001055# endif
H.J. Lu35be5812012-04-16 13:00:01 +02001056# ifdef X32
H.J. Lu085e4282012-04-17 11:05:04 -07001057 /* Value of currpers:
1058 * 0: 64 bit
1059 * 1: 32 bit
1060 * 2: X32
1061 * Value of current_personality:
1062 * 0: X32
1063 * 1: 32 bit
1064 */
1065 switch (currpers) {
1066 case 0:
1067 fprintf(stderr, "syscall_%lu (...) in unsupported "
1068 "64-bit mode of process PID=%d\n",
1069 scno, tcp->pid);
1070 return 0;
1071 case 2:
1072 currpers = 0;
H.J. Lu35be5812012-04-16 13:00:01 +02001073 }
H.J. Lu35be5812012-04-16 13:00:01 +02001074# endif
H.J. Lu085e4282012-04-17 11:05:04 -07001075 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001076#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001077# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001078 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001079 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001080 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001081 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001082 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001083 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001084 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001085 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001086 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001087#elif defined(AARCH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001088 switch (aarch64_io.iov_len) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001089 case sizeof(aarch64_regs):
1090 /* We are in 64-bit mode */
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001091 scno = aarch64_regs.regs[8];
1092 update_personality(tcp, 1);
1093 break;
1094 case sizeof(regs):
1095 /* We are in 32-bit mode */
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001096 scno = regs.uregs[7];
1097 update_personality(tcp, 0);
1098 break;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001099 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001100#elif defined(ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001101 /*
1102 * We only need to grab the syscall number on syscall entry.
1103 */
1104 if (regs.ARM_ip == 0) {
1105 /*
1106 * Note: we only deal with only 32-bit CPUs here.
1107 */
1108 if (regs.ARM_cpsr & 0x20) {
1109 /*
1110 * Get the Thumb-mode system call number
1111 */
1112 scno = regs.ARM_r7;
1113 } else {
1114 /*
1115 * Get the ARM-mode system call number
1116 */
1117 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +00001118 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +00001119 if (errno)
1120 return -1;
1121
Roland McGrathf691bd22006-04-25 07:34:41 +00001122 /* Handle the EABI syscall convention. We do not
1123 bother converting structures between the two
1124 ABIs, but basic functionality should work even
1125 if strace and the traced program have different
1126 ABIs. */
1127 if (scno == 0xef000000) {
1128 scno = regs.ARM_r7;
1129 } else {
1130 if ((scno & 0x0ff00000) != 0x0f900000) {
1131 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1132 scno);
1133 return -1;
1134 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001135
Roland McGrathf691bd22006-04-25 07:34:41 +00001136 /*
1137 * Fixup the syscall number
1138 */
1139 scno &= 0x000fffff;
1140 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001141 }
Roland McGrath56703312008-05-20 01:35:55 +00001142 if (scno & 0x0f0000) {
1143 /*
1144 * Handle ARM specific syscall
1145 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001146 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +00001147 scno &= 0x0000ffff;
1148 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001149 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001150
Roland McGrath0f87c492003-06-03 23:29:04 +00001151 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001152 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1153 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001154 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001155#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001156 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001157 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001158#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001159 unsigned long long regs[38];
1160
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001161 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001162 return -1;
1163 a3 = regs[REG_A3];
1164 r2 = regs[REG_V0];
1165
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001166 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001167 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001168 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001169 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001170 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001171 return 0;
1172 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001173 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001174#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001175 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001176 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001177 if (upeek(tcp, REG_V0, &scno) < 0)
1178 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001179
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001180 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001181 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001182 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001183 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001184 return 0;
1185 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001186 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001187#elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001188 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001189 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001190 if (upeek(tcp, REG_R0, &scno) < 0)
1191 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001192
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001193 /*
1194 * Do some sanity checks to figure out if it's
1195 * really a syscall entry
1196 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001197 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001198 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001199 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001200 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001201 return 0;
1202 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001203 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001204#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001205 /* Disassemble the syscall trap. */
1206 /* Retrieve the syscall trap instruction. */
1207 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001208# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001209 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1210 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001211# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001212 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001213# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001214 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001215 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001216
1217 /* Disassemble the trap to see what personality to use. */
1218 switch (trap) {
1219 case 0x91d02010:
1220 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001221 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001222 break;
1223 case 0x91d0206d:
1224 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001225 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001226 break;
1227 case 0x91d02000:
1228 /* SunOS syscall trap. (pers 1) */
1229 fprintf(stderr, "syscall: SunOS no support\n");
1230 return -1;
1231 case 0x91d02008:
1232 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001233 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001234 break;
1235 case 0x91d02009:
1236 /* NetBSD/FreeBSD syscall trap. */
1237 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1238 return -1;
1239 case 0x91d02027:
1240 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001241 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001242 break;
1243 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001244# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001245 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001246# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001247 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001248# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001249 return -1;
1250 }
1251
1252 /* Extract the system call number from the registers. */
1253 if (trap == 0x91d02027)
1254 scno = 156;
1255 else
1256 scno = regs.u_regs[U_REG_G1];
1257 if (scno == 0) {
1258 scno = regs.u_regs[U_REG_O0];
1259 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1260 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001261#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001262 if (upeek(tcp, PT_GR20, &scno) < 0)
1263 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001264#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001265 /*
1266 * In the new syscall ABI, the system call number is in R3.
1267 */
1268 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1269 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001270
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001271 if (scno < 0) {
1272 /* Odd as it may seem, a glibc bug has been known to cause
1273 glibc to issue bogus negative syscall numbers. So for
1274 our purposes, make strace print what it *should* have been */
1275 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001276 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001277 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001278 "Detected glibc bug: bogus system call"
1279 " number = %ld, correcting to %ld\n",
1280 scno,
1281 correct_scno);
1282 scno = correct_scno;
1283 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001284#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001285 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001286 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001287 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001288#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001289 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1290 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001291#elif defined(TILE)
Chris Metcalfc8c66982009-12-28 10:00:15 -05001292 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1293 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001294#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001295 if (upeek(tcp, 0, &scno) < 0)
1296 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001297#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001298
Denys Vlasenko523635f2012-02-25 02:44:25 +01001299#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001300 /* new syscall ABI returns result in R0 */
1301 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1302 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001303#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001304 /* ABI defines result returned in r9 */
1305 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1306 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001307#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001308
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001309 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001310 return 1;
1311}
1312
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001313/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001314 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001315 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1316 * 1: ok, continue in trace_syscall_entering().
1317 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001318 * ("????" etc) and bail out.
1319 */
Roland McGratha4d48532005-06-08 20:45:28 +00001320static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001321syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001322{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001323 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001324#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001325 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001326 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001327 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1328 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001329 }
H.J. Lu35be5812012-04-16 13:00:01 +02001330#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001331 {
1332 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001333 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001334 rax = (int)rax; /* sign extend from 32 bits */
1335 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001336 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001337 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1338 return 0;
1339 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001340 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001341#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001342 /* TODO: we already fetched PT_GPR2 in get_scno
1343 * and stored it in syscall_mode, reuse it here
1344 * instead of re-fetching?
1345 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001346 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001347 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001348 if (syscall_mode != -ENOSYS)
1349 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001350 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001351 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001352 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001353 return 0;
1354 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001355#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001356 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001357 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001358 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001359 if (d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001360 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001361 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001362 return 0;
1363 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001364#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001365 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001366 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001367 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001368 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001369 if (ia32 && r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001370 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001371 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001372 return 0;
1373 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001374#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001375 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001376 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001377 if (r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001378 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001379 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001380 return 0;
1381 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001382#elif defined(MICROBLAZE)
1383 if (upeek(tcp, 3 * 4, &r3) < 0)
1384 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001385 if (r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001386 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001387 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001388 return 0;
1389 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001390#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001391 return 1;
1392}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001393
Denys Vlasenko146b9442012-03-18 22:10:48 +01001394static void
1395internal_fork(struct tcb *tcp)
1396{
1397#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1398# define ARG_FLAGS 1
1399#else
1400# define ARG_FLAGS 0
1401#endif
1402#ifndef CLONE_UNTRACED
1403# define CLONE_UNTRACED 0x00800000
1404#endif
1405 if ((ptrace_setoptions
1406 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1407 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1408 return;
1409
1410 if (!followfork)
1411 return;
1412
1413 if (entering(tcp)) {
1414 /*
1415 * We won't see the new child if clone is called with
1416 * CLONE_UNTRACED, so we keep the same logic with that option
1417 * and don't trace it.
1418 */
1419 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1420 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1421 return;
1422 setbpt(tcp);
1423 } else {
1424 if (tcp->flags & TCB_BPTSET)
1425 clearbpt(tcp);
1426 }
1427}
1428
1429#if defined(TCB_WAITEXECVE)
1430static void
1431internal_exec(struct tcb *tcp)
1432{
1433 /* Maybe we have post-execve SIGTRAP suppressed? */
1434 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1435 return; /* yes, no need to do anything */
1436
1437 if (exiting(tcp) && syserror(tcp))
1438 /* Error in execve, no post-execve SIGTRAP expected */
1439 tcp->flags &= ~TCB_WAITEXECVE;
1440 else
1441 tcp->flags |= TCB_WAITEXECVE;
1442}
1443#endif
1444
1445static void
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001446internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001447{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001448 /*
1449 * We must always trace a few critical system calls in order to
1450 * correctly support following forks in the presence of tracing
1451 * qualifiers.
1452 */
1453 int (*func)();
1454
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001455 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001456 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001457
1458 func = sysent[tcp->scno].sys_func;
1459
1460 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001461 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001462 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001463 ) {
1464 internal_fork(tcp);
1465 return;
1466 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001467
Denys Vlasenko84703742012-02-25 02:38:52 +01001468#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001469 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001470# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001471 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001472# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001473 ) {
1474 internal_exec(tcp);
1475 return;
1476 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001477#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001478}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001479
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001480/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001481static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001482get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001483{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001484 int i, nargs;
1485
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001486 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001487 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001488 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001489 nargs = tcp->u_nargs = MAX_ARGS;
1490
Denys Vlasenko523635f2012-02-25 02:44:25 +01001491#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001492 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001493 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1494 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001495#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001496 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001497 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1498 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001499#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001500 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001501 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001502 long rbs_end;
1503 /* be backwards compatible with kernel < 2.4.4... */
1504# ifndef PT_RBS_END
1505# define PT_RBS_END PT_AR_BSP
1506# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001507
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001508 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1509 return -1;
1510 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001511 return -1;
1512
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001513 sof = (cfm >> 0) & 0x7f;
1514 sol = (cfm >> 7) & 0x7f;
1515 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1516
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001517 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001518 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1519 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1520 return -1;
1521 }
1522 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001523 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1524 PT_R9 /* ECX = out1 */,
1525 PT_R10 /* EDX = out2 */,
1526 PT_R14 /* ESI = out3 */,
1527 PT_R15 /* EDI = out4 */,
1528 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001529
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001530 for (i = 0; i < nargs; ++i) {
1531 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1532 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001533 /* truncate away IVE sign-extension */
1534 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001535 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001536 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001537#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001538 /* N32 and N64 both use up to six registers. */
1539 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001540
1541 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1542 return -1;
1543
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001544 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001545 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001546# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001547 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001548# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001549 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001550#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001551 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001552 long sp;
1553
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001554 if (upeek(tcp, REG_SP, &sp) < 0)
1555 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001556 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001557 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1558 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001559 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001560 (char *)(tcp->u_arg + 4));
1561 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001562 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001563 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001564 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001565 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001566#elif defined(POWERPC)
1567# ifndef PT_ORIG_R3
1568# define PT_ORIG_R3 34
1569# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001570 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001571 if (upeek(tcp, (i==0) ?
1572 (sizeof(unsigned long) * PT_ORIG_R3) :
1573 ((i+PT_R3) * sizeof(unsigned long)),
1574 &tcp->u_arg[i]) < 0)
1575 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001576 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001577#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001578 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001579 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001580#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001581 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001582 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1583 return -1;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001584#elif defined(ARM) || defined(AARCH64)
1585# if defined(AARCH64)
1586 if (tcp->currpers == 1)
1587 for (i = 0; i < nargs; ++i)
1588 tcp->u_arg[i] = aarch64_regs.regs[i];
1589 else
1590# endif /* AARCH64 */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001591 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001592 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001593#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001594 (void)i;
1595 (void)nargs;
1596 tcp->u_arg[0] = regs.r12;
1597 tcp->u_arg[1] = regs.r11;
1598 tcp->u_arg[2] = regs.r10;
1599 tcp->u_arg[3] = regs.r9;
1600 tcp->u_arg[4] = regs.r5;
1601 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001602#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001603 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 +02001604
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001605 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001606 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1607 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001608#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001609 static const int syscall_regs[MAX_ARGS] = {
1610 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1611 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001612 };
1613
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001614 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001615 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001616 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001617#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001618 int i;
1619 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001620 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001621
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001622 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001623 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1624 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001625#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001626 (void)i;
1627 (void)nargs;
H.J. Lu35be5812012-04-16 13:00:01 +02001628 if (current_personality != 1) { /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001629 tcp->u_arg[0] = x86_64_regs.rdi;
1630 tcp->u_arg[1] = x86_64_regs.rsi;
1631 tcp->u_arg[2] = x86_64_regs.rdx;
1632 tcp->u_arg[3] = x86_64_regs.r10;
1633 tcp->u_arg[4] = x86_64_regs.r8;
1634 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001635# ifdef X32
1636 tcp->ext_arg[0] = x86_64_regs.rdi;
1637 tcp->ext_arg[1] = x86_64_regs.rsi;
1638 tcp->ext_arg[2] = x86_64_regs.rdx;
1639 tcp->ext_arg[3] = x86_64_regs.r10;
1640 tcp->ext_arg[4] = x86_64_regs.r8;
1641 tcp->ext_arg[5] = x86_64_regs.r9;
1642# endif
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001643 } else { /* i386 ABI */
1644 /* Sign-extend lower 32 bits */
1645 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1646 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1647 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1648 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1649 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1650 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1651 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001652#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001653 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001654 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1655 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001656#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001657 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001658 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001659 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001660 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001661
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001662 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001663 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1664 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001665#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001666 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001667 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1668 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001669#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001670 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001671 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1672 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001673#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001674 (void)i;
1675 (void)nargs;
1676 tcp->u_arg[0] = i386_regs.ebx;
1677 tcp->u_arg[1] = i386_regs.ecx;
1678 tcp->u_arg[2] = i386_regs.edx;
1679 tcp->u_arg[3] = i386_regs.esi;
1680 tcp->u_arg[4] = i386_regs.edi;
1681 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001682#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001683 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001684 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1685 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001686#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001687 return 1;
1688}
1689
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001690static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001691trace_syscall_entering(struct tcb *tcp)
1692{
1693 int res, scno_good;
1694
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001695#if defined TCB_WAITEXECVE
1696 if (tcp->flags & TCB_WAITEXECVE) {
1697 /* This is the post-execve SIGTRAP. */
1698 tcp->flags &= ~TCB_WAITEXECVE;
1699 return 0;
1700 }
1701#endif
1702
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001703 scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001704 if (res == 0)
1705 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001706 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001707 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001708 if (res == 0)
1709 return res;
1710 if (res == 1)
1711 res = get_syscall_args(tcp);
1712 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001713
1714 if (res != 1) {
1715 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001716 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001717 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001718 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001719 tprintf("syscall_%lu(", tcp->scno);
1720 else
1721 tprintf("%s(", sysent[tcp->scno].sys_name);
1722 /*
1723 * " <unavailable>" will be added later by the code which
1724 * detects ptrace errors.
1725 */
1726 goto ret;
1727 }
1728
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001729#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1730 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001731# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001732 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001733 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001734 break;
1735 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001736# endif
1737# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001738 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001739 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001740 break;
1741 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001742# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001743 break;
1744 }
1745#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1746
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001747 internal_syscall(tcp);
1748
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001749 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001750 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1751 (tracing_paths && !pathtrace_match(tcp))) {
1752 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1753 return 0;
1754 }
1755
1756 tcp->flags &= ~TCB_FILTERED;
1757
1758 if (cflag == CFLAG_ONLY_STATS) {
1759 res = 0;
1760 goto ret;
1761 }
1762
1763 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001764 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001765 tprintf("syscall_%lu(", tcp->scno);
1766 else
1767 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001768 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001769 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1770 sysent[tcp->scno].sys_func != sys_exit))
1771 res = printargs(tcp);
1772 else
1773 res = (*sysent[tcp->scno].sys_func)(tcp);
1774
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001775 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001776 ret:
1777 tcp->flags |= TCB_INSYSCALL;
1778 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001779 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001780 gettimeofday(&tcp->etime, NULL);
1781 return res;
1782}
1783
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001784/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001785 * 1: ok, continue in trace_syscall_exiting().
1786 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001787 * ("????" etc) and bail out.
1788 */
1789static int
1790get_syscall_result(struct tcb *tcp)
1791{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001792#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001793 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1794 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001795#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001796# define SO_MASK 0x10000000
1797 {
1798 long flags;
1799 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1800 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001801 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001802 return -1;
1803 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001804 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001805 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001806#elif defined(AVR32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001807 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001808#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001809 if (upeek(tcp, PT_R0, &r0) < 0)
1810 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001811#elif defined(I386)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001812 /* already done by get_regs */
H.J. Lu35be5812012-04-16 13:00:01 +02001813#elif defined(X86_64) || defined(X32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001814 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001815#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001816# define IA64_PSR_IS ((long)1 << 34)
1817 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1818 ia32 = (psr & IA64_PSR_IS) != 0;
1819 if (upeek(tcp, PT_R8, &r8) < 0)
1820 return -1;
1821 if (upeek(tcp, PT_R10, &r10) < 0)
1822 return -1;
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001823#elif defined(AARCH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001824/* FIXME: uh, why do we do it on syscall *exit*? We did it on entry already... */
1825 /* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
1826 * else it's personality 0.
1827 */
1828 update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001829#elif defined(ARM)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001830 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001831#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001832 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1833 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001834#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001835 unsigned long long regs[38];
1836
1837 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1838 return -1;
1839 a3 = regs[REG_A3];
1840 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001841#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001842 if (upeek(tcp, REG_A3, &a3) < 0)
1843 return -1;
1844 if (upeek(tcp, REG_V0, &r2) < 0)
1845 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001846#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001847 if (upeek(tcp, REG_A3, &a3) < 0)
1848 return -1;
1849 if (upeek(tcp, REG_R0, &r0) < 0)
1850 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001851#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001852 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001853#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001854 if (upeek(tcp, PT_GR28, &r28) < 0)
1855 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001856#elif defined(SH)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001857 /* new syscall ABI returns result in R0 */
1858 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1859 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001860#elif defined(SH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001861 /* ABI defines result returned in r9 */
1862 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1863 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001864#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001865 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1866 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001867#elif defined(TILE)
1868#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001869 if (upeek(tcp, 3 * 4, &r3) < 0)
1870 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001871#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001872 return 1;
1873}
1874
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001875/* Called at each syscall exit */
1876static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001877syscall_fixup_on_sysexit(struct tcb *tcp)
1878{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001879#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001880 if (syscall_mode != -ENOSYS)
1881 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001882 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001883 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1884 /*
1885 * Return from execve.
1886 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1887 * flag set for the post-execve SIGTRAP to see and reset.
1888 */
1889 gpr2 = 0;
1890 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001891#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001892}
1893
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001894/*
1895 * Check the syscall return value register value for whether it is
1896 * a negated errno code indicating an error, or a success return value.
1897 */
1898static inline int
1899is_negated_errno(unsigned long int val)
1900{
1901 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001902#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001903 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001904 val = (unsigned int) val;
1905 max = (unsigned int) max;
1906 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001907#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001908 return val > max;
1909}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001910
Denys Vlasenko907735a2012-03-21 00:23:16 +01001911/* Returns:
1912 * 1: ok, continue in trace_syscall_exiting().
1913 * -1: error, trace_syscall_exiting() should print error indicator
1914 * ("????" etc) and bail out.
1915 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001916static int
1917get_error(struct tcb *tcp)
1918{
1919 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001920 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001921 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001922 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1923 check_errno = 0;
1924 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001925#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001926 if (check_errno && is_negated_errno(gpr2)) {
1927 tcp->u_rval = -1;
1928 u_error = -gpr2;
1929 }
1930 else {
1931 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001932 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001933#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001934 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001935 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001936 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001937 }
1938 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001939 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001940 }
H.J. Lu35be5812012-04-16 13:00:01 +02001941#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001942 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001943 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001944 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001945 }
1946 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001947 tcp->u_rval = x86_64_regs.rax;
H.J. Lu35be5812012-04-16 13:00:01 +02001948# if defined(X32)
1949 tcp->u_lrval = x86_64_regs.rax;
1950# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001951 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001952#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001953 if (ia32) {
1954 int err;
1955
1956 err = (int)r8;
1957 if (check_errno && is_negated_errno(err)) {
1958 tcp->u_rval = -1;
1959 u_error = -err;
1960 }
1961 else {
1962 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001963 }
1964 } else {
1965 if (check_errno && r10) {
1966 tcp->u_rval = -1;
1967 u_error = r8;
1968 } else {
1969 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001970 }
1971 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001972#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001973 if (check_errno && a3) {
1974 tcp->u_rval = -1;
1975 u_error = r2;
1976 } else {
1977 tcp->u_rval = r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02001978# if defined(LINUX_MIPSN32)
1979 tcp->u_lrval = r2;
1980# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001981 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001982#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001983 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001984 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001985 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001986 }
1987 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001988 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001989 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001990#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001991 if (check_errno && is_negated_errno(d0)) {
1992 tcp->u_rval = -1;
1993 u_error = -d0;
1994 }
1995 else {
1996 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001997 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001998#elif defined(ARM) || defined(AARCH64)
1999# if defined(AARCH64)
2000 if (tcp->currpers == 1) {
2001 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2002 tcp->u_rval = -1;
2003 u_error = -aarch64_regs.regs[0];
2004 }
2005 else {
2006 tcp->u_rval = aarch64_regs.regs[0];
2007 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002008 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002009 else
2010# endif /* AARCH64 */
2011 {
2012 if (check_errno && is_negated_errno(regs.ARM_r0)) {
2013 tcp->u_rval = -1;
2014 u_error = -regs.ARM_r0;
2015 }
2016 else {
2017 tcp->u_rval = regs.ARM_r0;
2018 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002019 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002020#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002021 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
2022 tcp->u_rval = -1;
2023 u_error = -regs.r12;
2024 }
2025 else {
2026 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002027 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002028#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002029 if (check_errno && is_negated_errno(r0)) {
2030 tcp->u_rval = -1;
2031 u_error = -r0;
2032 } else {
2033 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002034 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002035#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002036 if (check_errno && a3) {
2037 tcp->u_rval = -1;
2038 u_error = r0;
2039 }
2040 else {
2041 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002042 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002043#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002044 if (check_errno && regs.psr & PSR_C) {
2045 tcp->u_rval = -1;
2046 u_error = regs.u_regs[U_REG_O0];
2047 }
2048 else {
2049 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002050 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002051#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002052 if (check_errno && regs.tstate & 0x1100000000UL) {
2053 tcp->u_rval = -1;
2054 u_error = regs.u_regs[U_REG_O0];
2055 }
2056 else {
2057 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002058 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002059#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002060 if (check_errno && is_negated_errno(r28)) {
2061 tcp->u_rval = -1;
2062 u_error = -r28;
2063 }
2064 else {
2065 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002066 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002067#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002068 if (check_errno && is_negated_errno(r0)) {
2069 tcp->u_rval = -1;
2070 u_error = -r0;
2071 }
2072 else {
2073 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002074 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002075#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002076 if (check_errno && is_negated_errno(r9)) {
2077 tcp->u_rval = -1;
2078 u_error = -r9;
2079 }
2080 else {
2081 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002082 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002083#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002084 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
2085 tcp->u_rval = -1;
2086 u_error = -r10;
2087 }
2088 else {
2089 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002090 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002091#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002092 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002093 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
2094 return -1;
2095 if (check_errno && rval < 0 && rval > -nerrnos) {
2096 tcp->u_rval = -1;
2097 u_error = -rval;
2098 }
2099 else {
2100 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002101 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002102#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002103 if (check_errno && is_negated_errno(r3)) {
2104 tcp->u_rval = -1;
2105 u_error = -r3;
2106 }
2107 else {
2108 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002109 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002110#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002111 tcp->u_error = u_error;
2112 return 1;
2113}
2114
2115static void
2116dumpio(struct tcb *tcp)
2117{
2118 if (syserror(tcp))
2119 return;
2120 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
2121 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002122 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002123 return;
2124 if (sysent[tcp->scno].sys_func == printargs)
2125 return;
2126 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
2127 if (sysent[tcp->scno].sys_func == sys_read ||
2128 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002129 sysent[tcp->scno].sys_func == sys_recv ||
2130 sysent[tcp->scno].sys_func == sys_recvfrom)
2131 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
2132 else if (sysent[tcp->scno].sys_func == sys_readv)
2133 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2134 return;
2135 }
2136 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
2137 if (sysent[tcp->scno].sys_func == sys_write ||
2138 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002139 sysent[tcp->scno].sys_func == sys_send ||
2140 sysent[tcp->scno].sys_func == sys_sendto)
2141 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
2142 else if (sysent[tcp->scno].sys_func == sys_writev)
2143 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2144 return;
2145 }
2146}
2147
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002148static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002149trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002150{
2151 int sys_res;
2152 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002153 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002154 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002155
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002156 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002157 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002158 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002159
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002160#if SUPPORTED_PERSONALITIES > 1
2161 update_personality(tcp, tcp->currpers);
2162#endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002163 res = (get_regs_error ? -1 : get_syscall_result(tcp));
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002164 if (res == 1) {
2165 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01002166 res = get_error(tcp); /* returns 1 or -1 */
2167 if (res == 1) {
2168 internal_syscall(tcp);
2169 if (filtered(tcp)) {
2170 goto ret;
2171 }
2172 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002173 }
2174
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002175 if (cflag) {
2176 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002177 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002178 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002179 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002180 }
2181 }
2182
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002183 /* If not in -ff mode, and printing_tcp != tcp,
2184 * then the log currently does not end with output
2185 * of _our syscall entry_, but with something else.
2186 * We need to say which syscall's return is this.
2187 *
2188 * Forced reprinting via TCB_REPRINT is used only by
2189 * "strace -ff -oLOG test/threaded_execve" corner case.
2190 * It's the only case when -ff mode needs reprinting.
2191 */
2192 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2193 tcp->flags &= ~TCB_REPRINT;
2194 printleader(tcp);
2195 if (!SCNO_IN_RANGE(tcp->scno))
2196 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2197 else
2198 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2199 }
2200 printing_tcp = tcp;
2201
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002202 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002203 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002204 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002205 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002206 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002207 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002208 tcp->flags &= ~TCB_INSYSCALL;
2209 return res;
2210 }
2211
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002212 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002213 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002214 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002215 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002216 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002217 /* FIXME: not_failing_only (IOW, option -z) is broken:
2218 * failure of syscall is known only after syscall return.
2219 * Thus we end up with something like this on, say, ENOENT:
2220 * open("doesnt_exist", O_RDONLY <unfinished ...>
2221 * {next syscall decode}
2222 * whereas the intended result is that open(...) line
2223 * is not shown at all.
2224 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002225 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002226 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002227 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2228 }
2229
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002230 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002231 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002232 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002233 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002234 qual_flags[tcp->scno] & QUAL_RAW) {
2235 if (u_error)
2236 tprintf("= -1 (errno %ld)", u_error);
2237 else
2238 tprintf("= %#lx", tcp->u_rval);
2239 }
2240 else if (!(sys_res & RVAL_NONE) && u_error) {
2241 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002242 /* Blocked signals do not interrupt any syscalls.
2243 * In this case syscalls don't return ERESTARTfoo codes.
2244 *
2245 * Deadly signals set to SIG_DFL interrupt syscalls
2246 * and kill the process regardless of which of the codes below
2247 * is returned by the interrupted syscall.
2248 * In some cases, kernel forces a kernel-generated deadly
2249 * signal to be unblocked and set to SIG_DFL (and thus cause
2250 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2251 * or SIGILL. (The alternative is to leave process spinning
2252 * forever on the faulty instruction - not useful).
2253 *
2254 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2255 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2256 * but kernel will always restart them.
2257 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002258 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002259 /* Most common type of signal-interrupted syscall exit code.
2260 * The system call will be restarted with the same arguments
2261 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2262 */
2263 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002264 break;
2265 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002266 /* Rare. For example, fork() returns this if interrupted.
2267 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2268 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002269 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002270 break;
2271 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002272 /* pause(), rt_sigsuspend() etc use this code.
2273 * SA_RESTART is ignored (assumed not set):
2274 * syscall won't restart (will return EINTR instead)
2275 * even after signal with SA_RESTART set.
2276 * However, after SIG_IGN or SIG_DFL signal it will.
2277 */
2278 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002279 break;
2280 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002281 /* Syscalls like nanosleep(), poll() which can't be
2282 * restarted with their original arguments use this
2283 * code. Kernel will execute restart_syscall() instead,
2284 * which changes arguments before restarting syscall.
2285 * SA_RESTART is ignored (assumed not set) similarly
2286 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2287 * since restart data is saved in "restart block"
2288 * in task struct, and if signal handler uses a syscall
2289 * which in turn saves another such restart block,
2290 * old data is lost and restart becomes impossible)
2291 */
2292 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002293 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002294 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002295 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002296 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002297 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002298 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002299 strerror(u_error));
2300 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002301 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002302 strerror(u_error));
2303 break;
2304 }
2305 if ((sys_res & RVAL_STR) && tcp->auxstr)
2306 tprintf(" (%s)", tcp->auxstr);
2307 }
2308 else {
2309 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002310 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002311 else {
2312 switch (sys_res & RVAL_MASK) {
2313 case RVAL_HEX:
2314 tprintf("= %#lx", tcp->u_rval);
2315 break;
2316 case RVAL_OCTAL:
2317 tprintf("= %#lo", tcp->u_rval);
2318 break;
2319 case RVAL_UDECIMAL:
2320 tprintf("= %lu", tcp->u_rval);
2321 break;
2322 case RVAL_DECIMAL:
2323 tprintf("= %ld", tcp->u_rval);
2324 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002325#if defined(LINUX_MIPSN32) || defined(X32)
2326 /*
2327 case RVAL_LHEX:
2328 tprintf("= %#llx", tcp->u_lrval);
2329 break;
2330 case RVAL_LOCTAL:
2331 tprintf("= %#llo", tcp->u_lrval);
2332 break;
2333 */
2334 case RVAL_LUDECIMAL:
2335 tprintf("= %llu", tcp->u_lrval);
2336 break;
2337 /*
2338 case RVAL_LDECIMAL:
2339 tprintf("= %lld", tcp->u_lrval);
2340 break;
2341 */
2342#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002343 default:
2344 fprintf(stderr,
2345 "invalid rval format\n");
2346 break;
2347 }
2348 }
2349 if ((sys_res & RVAL_STR) && tcp->auxstr)
2350 tprintf(" (%s)", tcp->auxstr);
2351 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002352 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002353 tv_sub(&tv, &tv, &tcp->etime);
2354 tprintf(" <%ld.%06ld>",
2355 (long) tv.tv_sec, (long) tv.tv_usec);
2356 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002357 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002358 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002359 line_ended();
2360
Denys Vlasenko3b738812011-08-22 02:06:35 +02002361 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002362 tcp->flags &= ~TCB_INSYSCALL;
2363 return 0;
2364}
2365
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002366int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002367trace_syscall(struct tcb *tcp)
2368{
2369 return exiting(tcp) ?
2370 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2371}