blob: 433ee724ae15a6163d68a93fb1ff64b11837d6f4 [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
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +010068#if defined(X86_64) || defined(X32)
69# include <linux/ptrace.h>
70# include <asm/ptrace.h>
71# include <sys/uio.h>
72# include <elf.h>
73#endif
74
Steve McIntyred8d3bd32012-10-24 17:58:16 +010075#if defined(AARCH64)
76# include <asm/ptrace.h>
77# include <sys/uio.h>
78# include <elf.h>
79#endif
80
Christian Svensson492f81f2013-02-14 13:26:27 +010081#if defined(OR1K)
82# include <sys/uio.h>
83# include <elf.h>
84#endif
85
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000086#ifndef ERESTARTSYS
Denys Vlasenko523635f2012-02-25 02:44:25 +010087# define ERESTARTSYS 512
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000088#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010089#ifndef ERESTARTNOINTR
Denys Vlasenko523635f2012-02-25 02:44:25 +010090# define ERESTARTNOINTR 513
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000091#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010092#ifndef ERESTARTNOHAND
93# define ERESTARTNOHAND 514 /* restart if no handler */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000094#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010095#ifndef ERESTART_RESTARTBLOCK
Denys Vlasenko523635f2012-02-25 02:44:25 +010096# define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
Roland McGrath9c555e72003-07-09 09:47:59 +000097#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010098
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000099#ifndef NSIG
Denys Vlasenko523635f2012-02-25 02:44:25 +0100100# warning: NSIG is not defined, using 32
101# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102#endif
103#ifdef ARM
Denys Vlasenko041b3ee2011-08-18 12:48:56 +0200104/* Ugh. Is this really correct? ARM has no RT signals?! */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100105# undef NSIG
106# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000107#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000108
109#include "syscall.h"
110
111/* Define these shorthand notations to simplify the syscallent files. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000112#define TD TRACE_DESC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000113#define TF TRACE_FILE
114#define TI TRACE_IPC
115#define TN TRACE_NETWORK
116#define TP TRACE_PROCESS
117#define TS TRACE_SIGNAL
Namhyung Kim96792962012-10-24 11:41:57 +0900118#define TM TRACE_MEMORY
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000119#define NF SYSCALL_NEVER_FAILS
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200120#define MA MAX_ARGS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121
Roland McGrathee36ce12004-09-04 03:53:10 +0000122static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000123#include "syscallent.h"
124};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000125
126#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000127static const struct sysent sysent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100128# include "syscallent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000129};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200130#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000131
132#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000133static const struct sysent sysent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100134# include "syscallent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000135};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200136#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000137
138/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000139#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000140#undef TF
141#undef TI
142#undef TN
143#undef TP
144#undef TS
Namhyung Kim96792962012-10-24 11:41:57 +0900145#undef TM
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000146#undef NF
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200147#undef MA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000148
Denys Vlasenko39fca622011-08-20 02:12:33 +0200149/*
150 * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
151 * program `ioctlsort', such that the list is sorted by the `code' field.
152 * This has the side-effect of resolving the _IO.. macros into
153 * plain integers, eliminating the need to include here everything
154 * in "/usr/include".
155 */
156
Roland McGrathee36ce12004-09-04 03:53:10 +0000157static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000158#include "errnoent.h"
159};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200160static const char *const signalent0[] = {
161#include "signalent.h"
162};
163static const struct ioctlent ioctlent0[] = {
164#include "ioctlent.h"
165};
166enum { nsyscalls0 = ARRAY_SIZE(sysent0) };
167enum { nerrnos0 = ARRAY_SIZE(errnoent0) };
168enum { nsignals0 = ARRAY_SIZE(signalent0) };
169enum { nioctlents0 = ARRAY_SIZE(ioctlent0) };
170int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000171
172#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000173static const char *const errnoent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100174# include "errnoent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000175};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200176static const char *const signalent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100177# include "signalent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200178};
179static const struct ioctlent ioctlent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100180# include "ioctlent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200181};
182enum { nsyscalls1 = ARRAY_SIZE(sysent1) };
183enum { nerrnos1 = ARRAY_SIZE(errnoent1) };
184enum { nsignals1 = ARRAY_SIZE(signalent1) };
185enum { nioctlents1 = ARRAY_SIZE(ioctlent1) };
186int qual_flags1[MAX_QUALS];
187#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000188
189#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000190static const char *const errnoent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100191# include "errnoent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000192};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200193static const char *const signalent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100194# include "signalent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200195};
196static const struct ioctlent ioctlent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100197# include "ioctlent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200198};
199enum { nsyscalls2 = ARRAY_SIZE(sysent2) };
200enum { nerrnos2 = ARRAY_SIZE(errnoent2) };
201enum { nsignals2 = ARRAY_SIZE(signalent2) };
202enum { nioctlents2 = ARRAY_SIZE(ioctlent2) };
203int qual_flags2[MAX_QUALS];
204#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000205
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100206const struct sysent *sysent = sysent0;
207const char *const *errnoent = errnoent0;
208const char *const *signalent = signalent0;
209const struct ioctlent *ioctlent = ioctlent0;
210unsigned nsyscalls = nsyscalls0;
211unsigned nerrnos = nerrnos0;
212unsigned nsignals = nsignals0;
213unsigned nioctlents = nioctlents0;
214int *qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000215
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100216#if SUPPORTED_PERSONALITIES > 1
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000217int current_personality;
218
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000219const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
220 PERSONALITY0_WORDSIZE,
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000221 PERSONALITY1_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100222# if SUPPORTED_PERSONALITIES > 2
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000223 PERSONALITY2_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100224# endif
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200225};
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000226
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200227void
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000228set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000229{
230 switch (personality) {
231 case 0:
232 errnoent = errnoent0;
233 nerrnos = nerrnos0;
234 sysent = sysent0;
235 nsyscalls = nsyscalls0;
236 ioctlent = ioctlent0;
237 nioctlents = nioctlents0;
238 signalent = signalent0;
239 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000240 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000241 break;
242
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000243 case 1:
244 errnoent = errnoent1;
245 nerrnos = nerrnos1;
246 sysent = sysent1;
247 nsyscalls = nsyscalls1;
248 ioctlent = ioctlent1;
249 nioctlents = nioctlents1;
250 signalent = signalent1;
251 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000252 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000253 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000254
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100255# if SUPPORTED_PERSONALITIES >= 3
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000256 case 2:
257 errnoent = errnoent2;
258 nerrnos = nerrnos2;
259 sysent = sysent2;
260 nsyscalls = nsyscalls2;
261 ioctlent = ioctlent2;
262 nioctlents = nioctlents2;
263 signalent = signalent2;
264 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000265 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000266 break;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100267# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000268 }
269
270 current_personality = personality;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000271}
272
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000273static void
274update_personality(struct tcb *tcp, int personality)
275{
276 if (personality == current_personality)
277 return;
278 set_personality(personality);
279
280 if (personality == tcp->currpers)
281 return;
282 tcp->currpers = personality;
283
H.J. Lu35be5812012-04-16 13:00:01 +0200284# if defined(POWERPC64)
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000285 if (!qflag) {
286 static const char *const names[] = {"64 bit", "32 bit"};
287 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
288 tcp->pid, names[personality]);
289 }
H.J. Lu35be5812012-04-16 13:00:01 +0200290# elif defined(X86_64)
291 if (!qflag) {
292 static const char *const names[] = {"64 bit", "32 bit", "x32"};
293 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
294 tcp->pid, names[personality]);
295 }
H.J. Lu085e4282012-04-17 11:05:04 -0700296# elif defined(X32)
297 if (!qflag) {
298 static const char *const names[] = {"x32", "32 bit"};
299 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
300 tcp->pid, names[personality]);
301 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000302# elif defined(AARCH64)
303 if (!qflag) {
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100304 static const char *const names[] = {"32-bit", "AArch64"};
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000305 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
306 tcp->pid, names[personality]);
307 }
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100308# elif defined(TILE)
309 if (!qflag) {
310 static const char *const names[] = {"64-bit", "32-bit"};
311 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
312 tcp->pid, names[personality]);
313 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100314# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000315}
316#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000317
Roland McGrath9797ceb2002-12-30 10:23:00 +0000318static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000319
Roland McGrathe10e62a2004-09-04 04:20:43 +0000320static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000321 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000322 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000323 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000324 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000325} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000326 { QUAL_TRACE, "trace", qual_syscall, "system call" },
327 { QUAL_TRACE, "t", qual_syscall, "system call" },
328 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
329 { QUAL_ABBREV, "a", qual_syscall, "system call" },
330 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
331 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
332 { QUAL_RAW, "raw", qual_syscall, "system call" },
333 { QUAL_RAW, "x", qual_syscall, "system call" },
334 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
335 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
336 { QUAL_SIGNAL, "s", qual_signal, "signal" },
337 { QUAL_FAULT, "fault", qual_fault, "fault" },
338 { QUAL_FAULT, "faults", qual_fault, "fault" },
339 { QUAL_FAULT, "m", qual_fault, "fault" },
340 { QUAL_READ, "read", qual_desc, "descriptor" },
341 { QUAL_READ, "reads", qual_desc, "descriptor" },
342 { QUAL_READ, "r", qual_desc, "descriptor" },
343 { QUAL_WRITE, "write", qual_desc, "descriptor" },
344 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
345 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000346 { 0, NULL, NULL, NULL },
347};
348
Roland McGrath9797ceb2002-12-30 10:23:00 +0000349static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000350qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000351{
Roland McGrath138c6a32006-01-12 09:50:49 +0000352 if (pers == 0 || pers < 0) {
353 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000354 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000355 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000356 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000357 }
358
359#if SUPPORTED_PERSONALITIES >= 2
360 if (pers == 1 || pers < 0) {
361 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000362 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000363 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000364 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000365 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100366#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000367
368#if SUPPORTED_PERSONALITIES >= 3
369 if (pers == 2 || pers < 0) {
370 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000371 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000372 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000373 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000374 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100375#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000376}
377
378static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000379qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000380{
381 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000382 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000383
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100384 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000385 int i = string_to_uint(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000386 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000387 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000388 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000389 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000390 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000391 for (i = 0; i < nsyscalls0; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000392 if (sysent0[i].sys_name &&
393 strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000394 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000395 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000396 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000397
398#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000399 for (i = 0; i < nsyscalls1; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000400 if (sysent1[i].sys_name &&
401 strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000402 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000403 rc = 0;
404 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100405#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000406
407#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000408 for (i = 0; i < nsyscalls2; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000409 if (sysent2[i].sys_name &&
410 strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000411 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000412 rc = 0;
413 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100414#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000415
Roland McGrathfe6b3522005-02-02 04:40:11 +0000416 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000417}
418
419static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000420qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000421{
422 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000423
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100424 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000425 int signo = string_to_uint(s);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000426 if (signo < 0 || signo >= MAX_QUALS)
427 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000428 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000429 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000430 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000431 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000432 s += 3;
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100433 for (i = 0; i <= NSIG; i++) {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000434 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000435 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000436 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000437 }
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100438 }
Roland McGrath76421df2005-02-02 03:51:18 +0000439 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000440}
441
442static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000443qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000444{
445 return -1;
446}
447
448static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000449qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000450{
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100451 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000452 int desc = string_to_uint(s);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000453 if (desc < 0 || desc >= MAX_QUALS)
454 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000455 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000456 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000457 }
458 return -1;
459}
460
461static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000462lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000463{
464 if (strcmp(s, "file") == 0)
465 return TRACE_FILE;
466 if (strcmp(s, "ipc") == 0)
467 return TRACE_IPC;
468 if (strcmp(s, "network") == 0)
469 return TRACE_NETWORK;
470 if (strcmp(s, "process") == 0)
471 return TRACE_PROCESS;
472 if (strcmp(s, "signal") == 0)
473 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000474 if (strcmp(s, "desc") == 0)
475 return TRACE_DESC;
Namhyung Kim96792962012-10-24 11:41:57 +0900476 if (strcmp(s, "memory") == 0)
477 return TRACE_MEMORY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000478 return -1;
479}
480
481void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000482qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000483{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000484 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000485 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000486 char *copy;
487 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000488 int i, n;
489
490 opt = &qual_options[0];
491 for (i = 0; (p = qual_options[i].option_name); i++) {
492 n = strlen(p);
493 if (strncmp(s, p, n) == 0 && s[n] == '=') {
494 opt = &qual_options[i];
495 s += n + 1;
496 break;
497 }
498 }
499 not = 0;
500 if (*s == '!') {
501 not = 1;
502 s++;
503 }
504 if (strcmp(s, "none") == 0) {
505 not = 1 - not;
506 s = "all";
507 }
508 if (strcmp(s, "all") == 0) {
509 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000510 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000511 }
512 return;
513 }
514 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000515 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000516 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200517 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200518 if (!copy)
519 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000520 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000521 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000522 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000523 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000524 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000525
526#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000527 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000528 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000529 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100530#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000531
532#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000533 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000534 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000535 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100536#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000537
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000538 continue;
539 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000540 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100541 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000542 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000543 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000544 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000545 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000546 return;
547}
548
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000549#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000550static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000551decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000552{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000553 unsigned long addr;
554 unsigned int i, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000555
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000556 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
557 return;
558
559 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
560 addr = tcp->u_arg[1];
561 tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100562 size = current_wordsize;
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000563 for (i = 0; i < tcp->u_nargs; ++i) {
564 if (size == sizeof(int)) {
565 unsigned int arg;
566 if (umove(tcp, addr, &arg) < 0)
567 arg = 0;
568 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000569 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000570 else {
571 unsigned long arg;
572 if (umove(tcp, addr, &arg) < 0)
573 arg = 0;
574 tcp->u_arg[i] = arg;
575 }
576 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000577 }
578}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000579#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400580
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000581#ifdef SYS_ipc_subcall
582static void
583decode_ipc_subcall(struct tcb *tcp)
584{
585 unsigned int i;
586
587 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
588 return;
589
590 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
591 tcp->u_nargs = sysent[tcp->scno].nargs;
592 for (i = 0; i < tcp->u_nargs; i++)
593 tcp->u_arg[i] = tcp->u_arg[i + 1];
594}
595#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000596
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200597int
598printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000599{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200600 if (entering(tcp)) {
601 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000602
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200603 for (i = 0; i < tcp->u_nargs; i++)
604 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
605 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000606 return 0;
607}
608
Denys Vlasenko72879c62012-02-27 14:18:02 +0100609int
610printargs_lu(struct tcb *tcp)
611{
612 if (entering(tcp)) {
613 int i;
614
615 for (i = 0; i < tcp->u_nargs; i++)
616 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
617 }
618 return 0;
619}
620
621int
622printargs_ld(struct tcb *tcp)
623{
624 if (entering(tcp)) {
625 int i;
626
627 for (i = 0; i < tcp->u_nargs; i++)
628 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
629 }
630 return 0;
631}
632
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100633#if defined(SPARC) || defined(SPARC64) || defined(IA64) || defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200634long
635getrval2(struct tcb *tcp)
636{
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100637 long val;
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200638
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100639# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200640 val = regs.u_regs[U_REG_O1];
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100641# elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200642 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
643 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100644# elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200645 if (upeek(tcp, PT_R9, &val) < 0)
646 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100647# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200648
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200649 return val;
650}
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100651#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200652
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200653int
654is_restart_error(struct tcb *tcp)
655{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200656 switch (tcp->u_error) {
657 case ERESTARTSYS:
658 case ERESTARTNOINTR:
659 case ERESTARTNOHAND:
660 case ERESTART_RESTARTBLOCK:
661 return 1;
662 default:
663 break;
664 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200665 return 0;
666}
667
Denys Vlasenko523635f2012-02-25 02:44:25 +0100668#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100669struct pt_regs i386_regs;
H.J. Lu35be5812012-04-16 13:00:01 +0200670#elif defined(X86_64) || defined(X32)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100671/*
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100672 * On i386, pt_regs and user_regs_struct are the same,
673 * but on 64 bit x86, user_regs_struct has six more fields:
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100674 * fs_base, gs_base, ds, es, fs, gs.
675 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
676 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100677struct i386_user_regs_struct {
678 uint32_t ebx;
679 uint32_t ecx;
680 uint32_t edx;
681 uint32_t esi;
682 uint32_t edi;
683 uint32_t ebp;
684 uint32_t eax;
685 uint32_t xds;
686 uint32_t xes;
687 uint32_t xfs;
688 uint32_t xgs;
689 uint32_t orig_eax;
690 uint32_t eip;
691 uint32_t xcs;
692 uint32_t eflags;
693 uint32_t esp;
694 uint32_t xss;
695};
696static union {
697 struct user_regs_struct x86_64_r;
698 struct i386_user_regs_struct i386_r;
699} x86_regs_union;
700# define x86_64_regs x86_regs_union.x86_64_r
701# define i386_regs x86_regs_union.i386_r
702static struct iovec x86_io = {
703 .iov_base = &x86_regs_union
704};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100705#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200706long ia32 = 0; /* not static */
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100707static long ia64_r8, ia64_r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100708#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +0100709static long ppc_result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100710#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100711static long m68k_d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100712#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100713static long bfin_r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100714#elif defined(ARM)
Denys Vlasenko401374e2013-02-06 18:24:39 +0100715struct pt_regs arm_regs; /* not static */
Steve McIntyred8d3bd32012-10-24 17:58:16 +0100716#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100717static union {
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100718 struct user_pt_regs aarch64_r;
719 struct arm_pt_regs arm_r;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100720} arm_regs_union;
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100721# define aarch64_regs arm_regs_union.aarch64_r
722# define arm_regs arm_regs_union.arm_r
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100723static struct iovec aarch64_io = {
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100724 .iov_base = &arm_regs_union
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100725};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100726#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100727static long alpha_r0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100728static long alpha_a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100729#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200730static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100731#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100732struct pt_regs regs; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100733#elif defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100734static long long mips_a3;
735static long long mips_r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100736#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100737static long mips_a3;
738static long mips_r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100739#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200740static long gpr2;
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200741static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100742#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100743static long hppa_r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100744#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100745static long sh_r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100746#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100747static long sh64_r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100748#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100749static long cris_r10;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100750#elif defined(TILE)
751struct pt_regs tile_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100752#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100753static long microblaze_r3;
Christian Svensson492f81f2013-02-14 13:26:27 +0100754#elif defined(OR1K)
755static struct user_regs_struct or1k_regs;
756static struct iovec or1k_io = {
757 .iov_base = &or1k_regs
758};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100759#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000760
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100761void
762printcall(struct tcb *tcp)
763{
764#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
765 sizeof(long) == 8 ? "[????????????????] " : \
766 NULL /* crash */)
767 if (get_regs_error) {
768 PRINTBADPC;
769 return;
770 }
771#if defined(I386)
772 tprintf("[%08lx] ", i386_regs.eip);
773#elif defined(S390) || defined(S390X)
774 long psw;
775 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
776 PRINTBADPC;
777 return;
778 }
779# ifdef S390
780 tprintf("[%08lx] ", psw);
781# elif S390X
Dmitry V. Levinddba73e2013-02-05 19:01:58 +0000782 tprintf("[%016lx] ", psw);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100783# endif
784#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100785 if (x86_io.iov_len == sizeof(i386_regs)) {
786 tprintf("[%08x] ", (unsigned) i386_regs.eip);
787 } else {
788# if defined(X86_64)
789 tprintf("[%016lx] ", (unsigned long) x86_64_regs.rip);
790# elif defined(X32)
791 /* Note: this truncates 64-bit rip to 32 bits */
792 tprintf("[%08lx] ", (unsigned long) x86_64_regs.rip);
793# endif
794 }
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100795#elif defined(IA64)
796 long ip;
797
798 if (upeek(tcp, PT_B0, &ip) < 0) {
799 PRINTBADPC;
800 return;
801 }
802 tprintf("[%08lx] ", ip);
803#elif defined(POWERPC)
804 long pc;
805
806 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
807 PRINTBADPC;
808 return;
809 }
810# ifdef POWERPC64
811 tprintf("[%016lx] ", pc);
812# else
813 tprintf("[%08lx] ", pc);
814# endif
815#elif defined(M68K)
816 long pc;
817
818 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
819 tprints("[????????] ");
820 return;
821 }
822 tprintf("[%08lx] ", pc);
823#elif defined(ALPHA)
824 long pc;
825
826 if (upeek(tcp, REG_PC, &pc) < 0) {
827 tprints("[????????????????] ");
828 return;
829 }
830 tprintf("[%08lx] ", pc);
831#elif defined(SPARC)
832 tprintf("[%08lx] ", regs.pc);
833#elif defined(SPARC64)
834 tprintf("[%08lx] ", regs.tpc);
835#elif defined(HPPA)
836 long pc;
837
838 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
839 tprints("[????????] ");
840 return;
841 }
842 tprintf("[%08lx] ", pc);
843#elif defined(MIPS)
844 long pc;
845
846 if (upeek(tcp, REG_EPC, &pc) < 0) {
847 tprints("[????????] ");
848 return;
849 }
850 tprintf("[%08lx] ", pc);
851#elif defined(SH)
852 long pc;
853
854 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
855 tprints("[????????] ");
856 return;
857 }
858 tprintf("[%08lx] ", pc);
859#elif defined(SH64)
860 long pc;
861
862 if (upeek(tcp, REG_PC, &pc) < 0) {
863 tprints("[????????????????] ");
864 return;
865 }
866 tprintf("[%08lx] ", pc);
867#elif defined(ARM)
Denys Vlasenko401374e2013-02-06 18:24:39 +0100868 tprintf("[%08lx] ", arm_regs.ARM_pc);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100869#elif defined(AARCH64)
870 /* tprintf("[%016lx] ", aarch64_regs.regs[???]); */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100871#elif defined(AVR32)
872 tprintf("[%08lx] ", regs.pc);
873#elif defined(BFIN)
874 long pc;
875
876 if (upeek(tcp, PT_PC, &pc) < 0) {
877 PRINTBADPC;
878 return;
879 }
880 tprintf("[%08lx] ", pc);
881#elif defined(CRISV10)
882 long pc;
883
884 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
885 PRINTBADPC;
886 return;
887 }
888 tprintf("[%08lx] ", pc);
889#elif defined(CRISV32)
890 long pc;
891
892 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
893 PRINTBADPC;
894 return;
895 }
896 tprintf("[%08lx] ", pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100897#elif defined(TILE)
898# ifdef _LP64
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500899 tprintf("[%016lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100900# else
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500901 tprintf("[%08lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100902# endif
Christian Svensson492f81f2013-02-14 13:26:27 +0100903#elif defined(OR1K)
904 tprintf("[%08lx] ", or1k_regs.pc);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100905#endif /* architecture */
906}
907
908#ifndef get_regs
909long get_regs_error;
910void get_regs(pid_t pid)
911{
912# if defined(AVR32)
913 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
914# elif defined(I386)
915 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &i386_regs);
916# elif defined(X86_64) || defined(X32)
Denys Vlasenkoe3b248d2013-02-15 00:24:19 +0100917 /*
918 * PTRACE_GETREGSET was introduced in 2.6.33.
919 * Let's be paranoid and require a bit later kernel.
920 */
921 if (os_release >= KERNEL_VERSION(2,6,35)) {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100922 /*x86_io.iov_base = &x86_regs_union; - already is */
923 x86_io.iov_len = sizeof(x86_regs_union);
924 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (long) &x86_io);
925 } else {
926 /* Use old method, with heuristical detection of 32-bitness */
927 x86_io.iov_len = sizeof(x86_64_regs);
928 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &x86_64_regs);
929 if (!get_regs_error && x86_64_regs.cs == 0x23) {
930 x86_io.iov_len = sizeof(i386_regs);
931 /*
932 * The order is important: i386_regs and x86_64_regs
933 * are overlaid in memory!
934 */
935 i386_regs.ebx = x86_64_regs.rbx;
936 i386_regs.ecx = x86_64_regs.rcx;
937 i386_regs.edx = x86_64_regs.rdx;
938 i386_regs.esi = x86_64_regs.rsi;
939 i386_regs.edi = x86_64_regs.rdi;
940 i386_regs.ebp = x86_64_regs.rbp;
941 i386_regs.eax = x86_64_regs.rax;
942 /*i386_regs.xds = x86_64_regs.ds; unused by strace */
943 /*i386_regs.xes = x86_64_regs.es; ditto... */
944 /*i386_regs.xfs = x86_64_regs.fs;*/
945 /*i386_regs.xgs = x86_64_regs.gs;*/
946 i386_regs.orig_eax = x86_64_regs.orig_rax;
947 i386_regs.eip = x86_64_regs.rip;
948 /*i386_regs.xcs = x86_64_regs.cs;*/
949 /*i386_regs.eflags = x86_64_regs.eflags;*/
950 i386_regs.esp = x86_64_regs.rsp;
951 /*i386_regs.xss = x86_64_regs.ss;*/
952 }
953 }
Denys Vlasenko401374e2013-02-06 18:24:39 +0100954# elif defined(ARM)
955 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (void *)&arm_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100956# elif defined(AARCH64)
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100957 /*aarch64_io.iov_base = &arm_regs_union; - already is */
958 aarch64_io.iov_len = sizeof(arm_regs_union);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100959 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void *)&aarch64_io);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100960# if 0
961 /* Paranoia checks */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100962 if (get_regs_error)
963 return;
964 switch (aarch64_io.iov_len) {
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100965 case sizeof(aarch64_regs):
966 /* We are in 64-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100967 break;
968 case sizeof(arm_regs):
969 /* We are in 32-bit mode */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100970 break;
971 default:
972 get_regs_error = -1;
973 break;
974 }
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100975# endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100976# elif defined(SPARC) || defined(SPARC64)
977 get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&regs, 0);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100978# elif defined(TILE)
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500979 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &tile_regs);
Christian Svensson492f81f2013-02-14 13:26:27 +0100980# elif defined(OR1K)
981 or1k_io.iov_len = sizeof(or1k_regs);
982 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &or1k_io);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100983# endif
984}
985#endif
986
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200987/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100988 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
989 * 1: ok, continue in trace_syscall_entering().
990 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200991 * ("????" etc) and bail out.
992 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100993static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200994get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000995{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000996 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000997
Denys Vlasenko523635f2012-02-25 02:44:25 +0100998#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000999 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001000 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +00001001
1002 if (syscall_mode != -ENOSYS) {
1003 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001004 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +00001005 */
1006 scno = syscall_mode;
1007 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001008 /*
Michal Ludvig882eda82002-11-11 12:50:47 +00001009 * Old style of "passing" the scno via the SVC instruction.
1010 */
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001011 long psw;
Michal Ludvig882eda82002-11-11 12:50:47 +00001012 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001013 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +02001014 static const int gpr_offset[16] = {
1015 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
1016 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
1017 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
1018 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
1019 };
Roland McGrath761b5d72002-12-15 23:58:31 +00001020
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001021 if (upeek(tcp, PT_PSWADDR, &psw) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +00001022 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +00001023 errno = 0;
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001024 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(psw - sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +00001025 if (errno) {
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001026 perror_msg("%s", "peektext(psw-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +00001027 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +00001028 }
Michal Ludvig882eda82002-11-11 12:50:47 +00001029
1030 /*
1031 * We have to check if the SVC got executed directly or via an
1032 * EXECUTE instruction. In case of EXECUTE it is necessary to do
1033 * instruction decoding to derive the system call number.
1034 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
1035 * so that this doesn't work if a SVC opcode is part of an EXECUTE
1036 * opcode. Since there is no way to find out the opcode size this
1037 * is the best we can do...
1038 */
Michal Ludvig882eda82002-11-11 12:50:47 +00001039 if ((opcode & 0xff00) == 0x0a00) {
1040 /* SVC opcode */
1041 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +00001042 }
Michal Ludvig882eda82002-11-11 12:50:47 +00001043 else {
1044 /* SVC got executed by EXECUTE instruction */
1045
1046 /*
1047 * Do instruction decoding of EXECUTE. If you really want to
1048 * understand this, read the Principles of Operations.
1049 */
1050 svc_addr = (void *) (opcode & 0xfff);
1051
1052 tmp = 0;
1053 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001054 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001055 return -1;
1056 svc_addr += tmp;
1057
1058 tmp = 0;
1059 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001060 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001061 return -1;
1062 svc_addr += tmp;
1063
Denys Vlasenkofb036672009-01-23 16:30:26 +00001064 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +00001065 if (errno)
1066 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001067# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +00001068 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001069# else
Michal Ludvig882eda82002-11-11 12:50:47 +00001070 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001071# endif
Michal Ludvig882eda82002-11-11 12:50:47 +00001072 tmp = 0;
1073 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001074 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001075 return -1;
1076
1077 scno = (scno | tmp) & 0xff;
1078 }
1079 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001080#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001081 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001082 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001083# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001084 /* TODO: speed up strace by not doing this at every syscall.
1085 * We only need to do it after execve.
1086 */
1087 int currpers;
1088 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +02001089
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001090 /* Check for 64/32 bit mode. */
1091 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
1092 return -1;
1093 /* SF is bit 0 of MSR */
1094 if (val < 0)
1095 currpers = 0;
1096 else
1097 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001098 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001099# endif
1100#elif defined(AVR32)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001101 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001102#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001103 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001104 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001105#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001106 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +02001107#elif defined(X86_64) || defined(X32)
1108# ifndef __X32_SYSCALL_BIT
1109# define __X32_SYSCALL_BIT 0x40000000
1110# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001111 int currpers;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001112# if 1
1113 /* GETREGSET of NT_PRSTATUS tells us regset size,
1114 * which unambiguously detects i386.
1115 *
1116 * Linux kernel distinguishes x86-64 and x32 processes
1117 * solely by looking at __X32_SYSCALL_BIT:
1118 * arch/x86/include/asm/compat.h::is_x32_task():
1119 * if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)
1120 * return true;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001121 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001122 if (x86_io.iov_len == sizeof(i386_regs)) {
1123 scno = i386_regs.orig_eax;
1124 currpers = 1;
1125 } else {
1126 scno = x86_64_regs.orig_rax;
1127 currpers = 0;
1128 if (scno & __X32_SYSCALL_BIT) {
1129 scno -= __X32_SYSCALL_BIT;
1130 currpers = 2;
1131 }
1132 }
1133# elif 0
1134 /* cs = 0x33 for long mode (native 64 bit and x32)
1135 * cs = 0x23 for compatibility mode (32 bit)
1136 * ds = 0x2b for x32 mode (x86-64 in 32 bit)
1137 */
1138 scno = x86_64_regs.orig_rax;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001139 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001140 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +02001141 case 0x33:
1142 if (x86_64_regs.ds == 0x2b) {
1143 currpers = 2;
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001144 scno &= ~__X32_SYSCALL_BIT;
H.J. Lu35be5812012-04-16 13:00:01 +02001145 } else
1146 currpers = 0;
1147 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001148 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001149 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001150 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001151 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001152 currpers = current_personality;
1153 break;
1154 }
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001155# elif 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001156 /* This version analyzes the opcode of a syscall instruction.
1157 * (int 0x80 on i386 vs. syscall on x86-64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001158 * It works, but is too complicated, and strictly speaking, unreliable.
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001159 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001160 unsigned long call, rip = x86_64_regs.rip;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001161 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
1162 rip -= 2;
1163 errno = 0;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001164 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001165 if (errno)
1166 fprintf(stderr, "ptrace_peektext failed: %s\n",
1167 strerror(errno));
1168 switch (call & 0xffff) {
1169 /* x86-64: syscall = 0x0f 0x05 */
1170 case 0x050f: currpers = 0; break;
1171 /* i386: int 0x80 = 0xcd 0x80 */
1172 case 0x80cd: currpers = 1; break;
1173 default:
1174 currpers = current_personality;
1175 fprintf(stderr,
1176 "Unknown syscall opcode (0x%04X) while "
1177 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001178 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001179 break;
1180 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001181# endif
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001182
H.J. Lu35be5812012-04-16 13:00:01 +02001183# ifdef X32
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001184 /* If we are built for a x32 system, then personality 0 is x32
1185 * (not x86_64), and stracing of x86_64 apps is not supported.
1186 * Stracing of i386 apps is still supported.
H.J. Lu085e4282012-04-17 11:05:04 -07001187 */
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001188 if (currpers == 0) {
1189 fprintf(stderr, "syscall_%lu(...) in unsupported "
1190 "64-bit mode of process PID=%d\n",
1191 scno, tcp->pid);
1192 return 0;
H.J. Lu35be5812012-04-16 13:00:01 +02001193 }
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001194 currpers &= ~2; /* map 2,1 to 0,1 */
H.J. Lu35be5812012-04-16 13:00:01 +02001195# endif
H.J. Lu085e4282012-04-17 11:05:04 -07001196 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001197#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001198# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001199 long psr;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001200 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001201 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001202 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001203 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001204 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001205 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001206 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001207 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001208 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001209#elif defined(AARCH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001210 switch (aarch64_io.iov_len) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001211 case sizeof(aarch64_regs):
1212 /* We are in 64-bit mode */
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001213 scno = aarch64_regs.regs[8];
1214 update_personality(tcp, 1);
1215 break;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001216 case sizeof(arm_regs):
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001217 /* We are in 32-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001218 scno = arm_regs.ARM_r7;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001219 update_personality(tcp, 0);
1220 break;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001221 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001222#elif defined(ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001223 /*
1224 * We only need to grab the syscall number on syscall entry.
1225 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001226 if (arm_regs.ARM_ip == 0) {
Roland McGrath0f87c492003-06-03 23:29:04 +00001227 /*
Denys Vlasenko401374e2013-02-06 18:24:39 +01001228 * Note: we only deal with 32-bit CPUs here
Roland McGrath0f87c492003-06-03 23:29:04 +00001229 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001230 if (arm_regs.ARM_cpsr & 0x20) {
Roland McGrath0f87c492003-06-03 23:29:04 +00001231 /*
1232 * Get the Thumb-mode system call number
1233 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001234 scno = arm_regs.ARM_r7;
Roland McGrath0f87c492003-06-03 23:29:04 +00001235 } else {
1236 /*
1237 * Get the ARM-mode system call number
1238 */
1239 errno = 0;
Denys Vlasenko401374e2013-02-06 18:24:39 +01001240 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(arm_regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +00001241 if (errno)
1242 return -1;
1243
Roland McGrathf691bd22006-04-25 07:34:41 +00001244 /* Handle the EABI syscall convention. We do not
1245 bother converting structures between the two
1246 ABIs, but basic functionality should work even
1247 if strace and the traced program have different
1248 ABIs. */
1249 if (scno == 0xef000000) {
Denys Vlasenko401374e2013-02-06 18:24:39 +01001250 scno = arm_regs.ARM_r7;
Roland McGrathf691bd22006-04-25 07:34:41 +00001251 } else {
1252 if ((scno & 0x0ff00000) != 0x0f900000) {
1253 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1254 scno);
1255 return -1;
1256 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001257
Roland McGrathf691bd22006-04-25 07:34:41 +00001258 /*
1259 * Fixup the syscall number
1260 */
1261 scno &= 0x000fffff;
1262 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001263 }
Roland McGrath56703312008-05-20 01:35:55 +00001264 if (scno & 0x0f0000) {
1265 /*
1266 * Handle ARM specific syscall
1267 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001268 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +00001269 scno &= 0x0000ffff;
1270 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001271 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001272
Roland McGrath0f87c492003-06-03 23:29:04 +00001273 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001274 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1275 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001276 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001277#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001278 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001279 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001280#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001281 unsigned long long regs[38];
1282
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001283 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001284 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001285 mips_a3 = regs[REG_A3];
1286 mips_r2 = regs[REG_V0];
Roland McGrath542c2c62008-05-20 01:11:56 +00001287
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001288 scno = mips_r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001289 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001290 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001291 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001292 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001293 return 0;
1294 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001295 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001296#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001297 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001298 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001299 if (upeek(tcp, REG_V0, &scno) < 0)
1300 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001301
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001302 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001303 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001304 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001305 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001306 return 0;
1307 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001308 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001309#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001310 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001311 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001312 if (upeek(tcp, REG_R0, &scno) < 0)
1313 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001314
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001315 /*
1316 * Do some sanity checks to figure out if it's
1317 * really a syscall entry
1318 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001319 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001320 if (alpha_a3 == 0 || alpha_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001321 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001322 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001323 return 0;
1324 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001325 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001326#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001327 /* Disassemble the syscall trap. */
1328 /* Retrieve the syscall trap instruction. */
Denys Vlasenko46455822013-02-05 17:02:59 +01001329 unsigned long trap;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001330 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001331# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001332 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1333 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001334# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001335 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001336# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001337 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001338 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001339
1340 /* Disassemble the trap to see what personality to use. */
1341 switch (trap) {
1342 case 0x91d02010:
1343 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001344 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001345 break;
1346 case 0x91d0206d:
1347 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001348 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001349 break;
1350 case 0x91d02000:
1351 /* SunOS syscall trap. (pers 1) */
1352 fprintf(stderr, "syscall: SunOS no support\n");
1353 return -1;
1354 case 0x91d02008:
1355 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001356 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001357 break;
1358 case 0x91d02009:
1359 /* NetBSD/FreeBSD syscall trap. */
1360 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1361 return -1;
1362 case 0x91d02027:
1363 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001364 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001365 break;
1366 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001367# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001368 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001369# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001370 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001371# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001372 return -1;
1373 }
1374
1375 /* Extract the system call number from the registers. */
1376 if (trap == 0x91d02027)
1377 scno = 156;
1378 else
1379 scno = regs.u_regs[U_REG_G1];
1380 if (scno == 0) {
1381 scno = regs.u_regs[U_REG_O0];
1382 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1383 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001384#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001385 if (upeek(tcp, PT_GR20, &scno) < 0)
1386 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001387#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001388 /*
1389 * In the new syscall ABI, the system call number is in R3.
1390 */
1391 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1392 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001393
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001394 if (scno < 0) {
1395 /* Odd as it may seem, a glibc bug has been known to cause
1396 glibc to issue bogus negative syscall numbers. So for
1397 our purposes, make strace print what it *should* have been */
1398 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001399 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001400 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001401 "Detected glibc bug: bogus system call"
1402 " number = %ld, correcting to %ld\n",
1403 scno,
1404 correct_scno);
1405 scno = correct_scno;
1406 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001407#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001408 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001409 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001410 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001411#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001412 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1413 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001414#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001415 int currpers;
1416 scno = tile_regs.regs[10];
1417# ifdef __tilepro__
1418 currpers = 1;
1419# else
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001420# ifndef PT_FLAGS_COMPAT
1421# define PT_FLAGS_COMPAT 0x10000 /* from Linux 3.8 on */
1422# endif
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001423 if (tile_regs.flags & PT_FLAGS_COMPAT)
1424 currpers = 1;
1425 else
1426 currpers = 0;
1427# endif
1428 update_personality(tcp, currpers);
1429
1430 if (!(tcp->flags & TCB_INSYSCALL)) {
1431 /* Check if we return from execve. */
1432 if (tcp->flags & TCB_WAITEXECVE) {
1433 tcp->flags &= ~TCB_WAITEXECVE;
1434 return 0;
1435 }
1436 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001437#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001438 if (upeek(tcp, 0, &scno) < 0)
1439 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01001440#elif defined(OR1K)
1441 scno = or1k_regs.gpr[11];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001442#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001443
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001444 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001445 return 1;
1446}
1447
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001448/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001449 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001450 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1451 * 1: ok, continue in trace_syscall_entering().
1452 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001453 * ("????" etc) and bail out.
1454 */
Roland McGratha4d48532005-06-08 20:45:28 +00001455static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001456syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001457{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001458 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001459#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001460 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001461 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001462 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1463 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001464 }
H.J. Lu35be5812012-04-16 13:00:01 +02001465#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001466 {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001467 long rax;
1468 if (x86_io.iov_len == sizeof(i386_regs)) {
1469 /* Sign extend from 32 bits */
1470 rax = (int32_t)i386_regs.eax;
1471 } else {
1472 /* Note: in X32 build, this truncates 64 to 32 bits */
1473 rax = x86_64_regs.rax;
1474 }
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001475 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001476 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001477 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1478 return 0;
1479 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001480 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001481#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001482 /* TODO: we already fetched PT_GPR2 in get_scno
1483 * and stored it in syscall_mode, reuse it here
1484 * instead of re-fetching?
1485 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001486 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001487 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001488 if (syscall_mode != -ENOSYS)
1489 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001490 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001491 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001492 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001493 return 0;
1494 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001495#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001496 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001497 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001498 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001499 if (m68k_d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001500 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001501 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", m68k_d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001502 return 0;
1503 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001504#elif defined(IA64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001505 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001506 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001507 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001508 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001509 if (ia32 && ia64_r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001510 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001511 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", ia64_r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001512 return 0;
1513 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001514#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001515 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001516 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001517 if (cris_r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001518 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001519 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", cris_r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001520 return 0;
1521 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001522#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001523 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001524 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001525 if (microblaze_r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001526 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001527 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", microblaze_r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001528 return 0;
1529 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001530#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001531 return 1;
1532}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001533
Denys Vlasenko146b9442012-03-18 22:10:48 +01001534static void
1535internal_fork(struct tcb *tcp)
1536{
1537#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1538# define ARG_FLAGS 1
1539#else
1540# define ARG_FLAGS 0
1541#endif
1542#ifndef CLONE_UNTRACED
1543# define CLONE_UNTRACED 0x00800000
1544#endif
1545 if ((ptrace_setoptions
1546 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1547 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1548 return;
1549
1550 if (!followfork)
1551 return;
1552
1553 if (entering(tcp)) {
1554 /*
1555 * We won't see the new child if clone is called with
1556 * CLONE_UNTRACED, so we keep the same logic with that option
1557 * and don't trace it.
1558 */
1559 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1560 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1561 return;
1562 setbpt(tcp);
1563 } else {
1564 if (tcp->flags & TCB_BPTSET)
1565 clearbpt(tcp);
1566 }
1567}
1568
1569#if defined(TCB_WAITEXECVE)
1570static void
1571internal_exec(struct tcb *tcp)
1572{
1573 /* Maybe we have post-execve SIGTRAP suppressed? */
1574 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1575 return; /* yes, no need to do anything */
1576
1577 if (exiting(tcp) && syserror(tcp))
1578 /* Error in execve, no post-execve SIGTRAP expected */
1579 tcp->flags &= ~TCB_WAITEXECVE;
1580 else
1581 tcp->flags |= TCB_WAITEXECVE;
1582}
1583#endif
1584
1585static void
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001586syscall_fixup_for_fork_exec(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001587{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001588 /*
1589 * We must always trace a few critical system calls in order to
1590 * correctly support following forks in the presence of tracing
1591 * qualifiers.
1592 */
1593 int (*func)();
1594
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001595 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001596 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001597
1598 func = sysent[tcp->scno].sys_func;
1599
1600 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001601 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001602 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001603 ) {
1604 internal_fork(tcp);
1605 return;
1606 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001607
Denys Vlasenko84703742012-02-25 02:38:52 +01001608#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001609 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001610# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001611 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001612# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001613 ) {
1614 internal_exec(tcp);
1615 return;
1616 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001617#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001618}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001619
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001620/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001621static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001622get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001623{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001624 int i, nargs;
1625
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001626 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001627 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001628 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001629 nargs = tcp->u_nargs = MAX_ARGS;
1630
Denys Vlasenko523635f2012-02-25 02:44:25 +01001631#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001632 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001633 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1634 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001635#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001636 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001637 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1638 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001639#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001640 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001641 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001642 long rbs_end;
1643 /* be backwards compatible with kernel < 2.4.4... */
1644# ifndef PT_RBS_END
1645# define PT_RBS_END PT_AR_BSP
1646# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001647
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001648 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1649 return -1;
1650 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001651 return -1;
1652
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001653 sof = (cfm >> 0) & 0x7f;
1654 sol = (cfm >> 7) & 0x7f;
1655 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1656
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001657 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001658 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1659 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1660 return -1;
1661 }
1662 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001663 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1664 PT_R9 /* ECX = out1 */,
1665 PT_R10 /* EDX = out2 */,
1666 PT_R14 /* ESI = out3 */,
1667 PT_R15 /* EDI = out4 */,
1668 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001669
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001670 for (i = 0; i < nargs; ++i) {
1671 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1672 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001673 /* truncate away IVE sign-extension */
1674 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001675 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001676 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001677#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001678 /* N32 and N64 both use up to six registers. */
1679 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001680
1681 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1682 return -1;
1683
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001684 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001685 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001686# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001687 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001688# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001689 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001690#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001691 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001692 long sp;
1693
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001694 if (upeek(tcp, REG_SP, &sp) < 0)
1695 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001696 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001697 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1698 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001699 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001700 (char *)(tcp->u_arg + 4));
1701 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001702 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001703 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001704 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001705 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001706#elif defined(POWERPC)
1707# ifndef PT_ORIG_R3
1708# define PT_ORIG_R3 34
1709# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001710 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001711 if (upeek(tcp, (i==0) ?
1712 (sizeof(unsigned long) * PT_ORIG_R3) :
1713 ((i+PT_R3) * sizeof(unsigned long)),
1714 &tcp->u_arg[i]) < 0)
1715 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001716 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001717#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001718 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001719 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001720#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001721 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001722 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1723 return -1;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001724#elif defined(ARM) || defined(AARCH64)
1725# if defined(AARCH64)
1726 if (tcp->currpers == 1)
1727 for (i = 0; i < nargs; ++i)
1728 tcp->u_arg[i] = aarch64_regs.regs[i];
1729 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001730# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001731 for (i = 0; i < nargs; ++i)
Denys Vlasenko401374e2013-02-06 18:24:39 +01001732 tcp->u_arg[i] = arm_regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001733#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001734 (void)i;
1735 (void)nargs;
1736 tcp->u_arg[0] = regs.r12;
1737 tcp->u_arg[1] = regs.r11;
1738 tcp->u_arg[2] = regs.r10;
1739 tcp->u_arg[3] = regs.r9;
1740 tcp->u_arg[4] = regs.r5;
1741 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001742#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001743 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 +02001744
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001745 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001746 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1747 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001748#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001749 static const int syscall_regs[MAX_ARGS] = {
1750 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1751 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001752 };
1753
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001754 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001755 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001756 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001757#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001758 int i;
1759 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001760 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001761
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001762 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001763 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1764 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001765#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001766 (void)i;
1767 (void)nargs;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001768 if (x86_io.iov_len != sizeof(i386_regs)) {
1769 /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001770 tcp->u_arg[0] = x86_64_regs.rdi;
1771 tcp->u_arg[1] = x86_64_regs.rsi;
1772 tcp->u_arg[2] = x86_64_regs.rdx;
1773 tcp->u_arg[3] = x86_64_regs.r10;
1774 tcp->u_arg[4] = x86_64_regs.r8;
1775 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001776# ifdef X32
1777 tcp->ext_arg[0] = x86_64_regs.rdi;
1778 tcp->ext_arg[1] = x86_64_regs.rsi;
1779 tcp->ext_arg[2] = x86_64_regs.rdx;
1780 tcp->ext_arg[3] = x86_64_regs.r10;
1781 tcp->ext_arg[4] = x86_64_regs.r8;
1782 tcp->ext_arg[5] = x86_64_regs.r9;
1783# endif
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001784 } else {
1785 /* i386 ABI */
1786 /* Sign-extend from 32 bits */
1787 tcp->u_arg[0] = (long)(int32_t)i386_regs.ebx;
1788 tcp->u_arg[1] = (long)(int32_t)i386_regs.ecx;
1789 tcp->u_arg[2] = (long)(int32_t)i386_regs.edx;
1790 tcp->u_arg[3] = (long)(int32_t)i386_regs.esi;
1791 tcp->u_arg[4] = (long)(int32_t)i386_regs.edi;
1792 tcp->u_arg[5] = (long)(int32_t)i386_regs.ebp;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001793 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001794#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001795 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001796 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1797 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001798#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001799 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001800 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001801 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001802 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001803
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001804 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001805 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1806 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001807#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001808 for (i = 0; i < nargs; ++i)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001809 tcp->u_arg[i] = tile_regs.regs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001810#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001811 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001812 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1813 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001814#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001815 (void)i;
1816 (void)nargs;
1817 tcp->u_arg[0] = i386_regs.ebx;
1818 tcp->u_arg[1] = i386_regs.ecx;
1819 tcp->u_arg[2] = i386_regs.edx;
1820 tcp->u_arg[3] = i386_regs.esi;
1821 tcp->u_arg[4] = i386_regs.edi;
1822 tcp->u_arg[5] = i386_regs.ebp;
Christian Svensson492f81f2013-02-14 13:26:27 +01001823#elif defined(OR1K)
1824 (void)nargs;
1825 for (i = 0; i < 6; ++i)
1826 tcp->u_arg[i] = or1k_regs.gpr[3 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001827#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001828 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001829 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1830 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001831#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001832 return 1;
1833}
1834
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001835static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001836trace_syscall_entering(struct tcb *tcp)
1837{
1838 int res, scno_good;
1839
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001840#if defined TCB_WAITEXECVE
1841 if (tcp->flags & TCB_WAITEXECVE) {
1842 /* This is the post-execve SIGTRAP. */
1843 tcp->flags &= ~TCB_WAITEXECVE;
1844 return 0;
1845 }
1846#endif
1847
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001848 scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001849 if (res == 0)
1850 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001851 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001852 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001853 if (res == 0)
1854 return res;
1855 if (res == 1)
1856 res = get_syscall_args(tcp);
1857 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001858
1859 if (res != 1) {
1860 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001861 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001862 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001863 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001864 tprintf("syscall_%lu(", tcp->scno);
1865 else
1866 tprintf("%s(", sysent[tcp->scno].sys_name);
1867 /*
1868 * " <unavailable>" will be added later by the code which
1869 * detects ptrace errors.
1870 */
1871 goto ret;
1872 }
1873
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001874#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1875 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001876# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001877 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001878 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001879 break;
1880 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001881# endif
1882# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001883 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001884 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001885 break;
1886 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001887# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001888 break;
1889 }
1890#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1891
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001892 if (need_fork_exec_workarounds)
1893 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001894
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001895 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001896 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1897 (tracing_paths && !pathtrace_match(tcp))) {
1898 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1899 return 0;
1900 }
1901
1902 tcp->flags &= ~TCB_FILTERED;
1903
1904 if (cflag == CFLAG_ONLY_STATS) {
1905 res = 0;
1906 goto ret;
1907 }
1908
1909 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001910 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001911 tprintf("syscall_%lu(", tcp->scno);
1912 else
1913 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001914 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001915 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1916 sysent[tcp->scno].sys_func != sys_exit))
1917 res = printargs(tcp);
1918 else
1919 res = (*sysent[tcp->scno].sys_func)(tcp);
1920
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001921 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001922 ret:
1923 tcp->flags |= TCB_INSYSCALL;
1924 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001925 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001926 gettimeofday(&tcp->etime, NULL);
1927 return res;
1928}
1929
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001930/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001931 * 1: ok, continue in trace_syscall_exiting().
1932 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001933 * ("????" etc) and bail out.
1934 */
1935static int
1936get_syscall_result(struct tcb *tcp)
1937{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001938#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001939 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1940 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001941#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001942# define SO_MASK 0x10000000
1943 {
1944 long flags;
1945 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1946 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001947 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001948 return -1;
1949 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001950 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001951 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001952#elif defined(AVR32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001953 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001954#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001955 if (upeek(tcp, PT_R0, &bfin_r0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001956 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001957#elif defined(I386)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001958 /* already done by get_regs */
H.J. Lu35be5812012-04-16 13:00:01 +02001959#elif defined(X86_64) || defined(X32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001960 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001961#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001962# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001963 long psr;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001964 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1965 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001966 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001967 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001968 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001969 return -1;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001970#elif defined(ARM)
1971 /* already done by get_regs */
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001972#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001973 /* register reading already done by get_regs */
1974
1975 /* Used to do this, but we did it on syscall entry already: */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001976 /* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
1977 * else it's personality 0.
1978 */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001979 /*update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));*/
Denys Vlasenko523635f2012-02-25 02:44:25 +01001980#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001981 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001982 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001983#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001984 unsigned long long regs[38];
1985
1986 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1987 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001988 mips_a3 = regs[REG_A3];
1989 mips_r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001990#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001991 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001992 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001993 if (upeek(tcp, REG_V0, &mips_r2) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001994 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001995#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001996 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001997 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001998 if (upeek(tcp, REG_R0, &alpha_r0) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001999 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002000#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002001 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002002#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002003 if (upeek(tcp, PT_GR28, &hppa_r28) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002004 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002005#elif defined(SH)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002006 /* new syscall ABI returns result in R0 */
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002007 if (upeek(tcp, 4*REG_REG0, (long *)&sh_r0) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002008 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002009#elif defined(SH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002010 /* ABI defines result returned in r9 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002011 if (upeek(tcp, REG_GENERAL(9), (long *)&sh64_r9) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002012 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002013#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002014 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002015 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002016#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002017 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002018#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002019 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002020 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01002021#elif defined(OR1K)
2022 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002023#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002024 return 1;
2025}
2026
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002027/* Called at each syscall exit */
2028static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002029syscall_fixup_on_sysexit(struct tcb *tcp)
2030{
Denys Vlasenko523635f2012-02-25 02:44:25 +01002031#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002032 if (syscall_mode != -ENOSYS)
2033 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02002034 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002035 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
2036 /*
2037 * Return from execve.
2038 * Fake a return value of zero. We leave the TCB_WAITEXECVE
2039 * flag set for the post-execve SIGTRAP to see and reset.
2040 */
2041 gpr2 = 0;
2042 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002043#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002044}
2045
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002046/*
2047 * Check the syscall return value register value for whether it is
2048 * a negated errno code indicating an error, or a success return value.
2049 */
2050static inline int
2051is_negated_errno(unsigned long int val)
2052{
2053 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002054#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01002055 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002056 val = (unsigned int) val;
2057 max = (unsigned int) max;
2058 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002059#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002060 return val > max;
2061}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002062
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002063#if defined(X32)
2064static inline int
2065is_negated_errno_x32(unsigned long long val)
2066{
2067 unsigned long long max = -(long long) nerrnos;
2068 /*
2069 * current_wordsize is 4 even in personality 0 (native X32)
2070 * but truncation _must not_ be done in it.
2071 * can't check current_wordsize here!
2072 */
2073 if (current_personality != 0) {
2074 val = (uint32_t) val;
2075 max = (uint32_t) max;
2076 }
2077 return val > max;
2078}
2079#endif
2080
Denys Vlasenko907735a2012-03-21 00:23:16 +01002081/* Returns:
2082 * 1: ok, continue in trace_syscall_exiting().
2083 * -1: error, trace_syscall_exiting() should print error indicator
2084 * ("????" etc) and bail out.
2085 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002086static int
2087get_error(struct tcb *tcp)
2088{
2089 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002090 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002091 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002092 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
2093 check_errno = 0;
2094 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002095#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002096 if (check_errno && is_negated_errno(gpr2)) {
2097 tcp->u_rval = -1;
2098 u_error = -gpr2;
2099 }
2100 else {
2101 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002102 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002103#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002104 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002105 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002106 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002107 }
2108 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002109 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002110 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002111#elif defined(X86_64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002112 long rax;
2113 if (x86_io.iov_len == sizeof(i386_regs)) {
2114 /* Sign extend from 32 bits */
2115 rax = (int32_t)i386_regs.eax;
2116 } else {
2117 rax = x86_64_regs.rax;
2118 }
2119 if (check_errno && is_negated_errno(rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002120 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002121 u_error = -rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002122 }
2123 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002124 tcp->u_rval = rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002125 }
2126#elif defined(X32)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002127 /* In X32, return value is 64-bit (llseek uses one).
2128 * Using merely "long rax" would not work.
2129 */
2130 long long rax;
2131 if (x86_io.iov_len == sizeof(i386_regs)) {
2132 /* Sign extend from 32 bits */
2133 rax = (int32_t)i386_regs.eax;
2134 } else {
2135 rax = x86_64_regs.rax;
2136 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002137 /* Careful: is_negated_errno() works only on longs */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002138 if (check_errno && is_negated_errno_x32(rax)) {
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002139 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002140 u_error = -rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002141 }
2142 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002143 tcp->u_rval = rax; /* truncating */
2144 tcp->u_lrval = rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002145 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002146#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002147 if (ia32) {
2148 int err;
2149
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002150 err = (int)ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002151 if (check_errno && is_negated_errno(err)) {
2152 tcp->u_rval = -1;
2153 u_error = -err;
2154 }
2155 else {
2156 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002157 }
2158 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002159 if (check_errno && ia64_r10) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002160 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002161 u_error = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002162 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002163 tcp->u_rval = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002164 }
2165 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002166#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002167 if (check_errno && mips_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002168 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002169 u_error = mips_r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002170 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002171 tcp->u_rval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002172# if defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002173 tcp->u_lrval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002174# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002175 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002176#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002177 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002178 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002179 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002180 }
2181 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002182 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002183 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002184#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002185 if (check_errno && is_negated_errno(m68k_d0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002186 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002187 u_error = -m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002188 }
2189 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002190 tcp->u_rval = m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002191 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002192#elif defined(ARM) || defined(AARCH64)
2193# if defined(AARCH64)
2194 if (tcp->currpers == 1) {
2195 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2196 tcp->u_rval = -1;
2197 u_error = -aarch64_regs.regs[0];
2198 }
2199 else {
2200 tcp->u_rval = aarch64_regs.regs[0];
2201 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002202 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002203 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01002204# endif
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002205 {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002206 if (check_errno && is_negated_errno(arm_regs.ARM_r0)) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002207 tcp->u_rval = -1;
Denys Vlasenko401374e2013-02-06 18:24:39 +01002208 u_error = -arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002209 }
2210 else {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002211 tcp->u_rval = arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002212 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002213 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002214#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002215 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
2216 tcp->u_rval = -1;
2217 u_error = -regs.r12;
2218 }
2219 else {
2220 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002221 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002222#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002223 if (check_errno && is_negated_errno(bfin_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002224 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002225 u_error = -bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002226 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002227 tcp->u_rval = bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002228 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002229#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002230 if (check_errno && alpha_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002231 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002232 u_error = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002233 }
2234 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002235 tcp->u_rval = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002236 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002237#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002238 if (check_errno && regs.psr & PSR_C) {
2239 tcp->u_rval = -1;
2240 u_error = regs.u_regs[U_REG_O0];
2241 }
2242 else {
2243 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002244 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002245#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002246 if (check_errno && regs.tstate & 0x1100000000UL) {
2247 tcp->u_rval = -1;
2248 u_error = regs.u_regs[U_REG_O0];
2249 }
2250 else {
2251 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002252 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002253#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002254 if (check_errno && is_negated_errno(hppa_r28)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002255 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002256 u_error = -hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002257 }
2258 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002259 tcp->u_rval = hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002260 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002261#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002262 if (check_errno && is_negated_errno(sh_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002263 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002264 u_error = -sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002265 }
2266 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002267 tcp->u_rval = sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002268 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002269#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002270 if (check_errno && is_negated_errno(sh64_r9)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002271 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002272 u_error = -sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002273 }
2274 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002275 tcp->u_rval = sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002276 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002277#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002278 if (check_errno && cris_r10 && (unsigned) -cris_r10 < nerrnos) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002279 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002280 u_error = -cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002281 }
2282 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002283 tcp->u_rval = cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002284 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002285#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002286 /*
2287 * The standard tile calling convention returns the value (or negative
2288 * errno) in r0, and zero (or positive errno) in r1.
2289 * Until at least kernel 3.8, however, the r1 value is not reflected
2290 * in ptregs at this point, so we use r0 here.
2291 */
2292 if (check_errno && is_negated_errno(tile_regs.regs[0])) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002293 tcp->u_rval = -1;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002294 u_error = -tile_regs.regs[0];
2295 } else {
2296 tcp->u_rval = tile_regs.regs[0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002297 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002298#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002299 if (check_errno && is_negated_errno(microblaze_r3)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002300 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002301 u_error = -microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002302 }
2303 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002304 tcp->u_rval = microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002305 }
Christian Svensson492f81f2013-02-14 13:26:27 +01002306#elif defined(OR1K)
2307 if (check_errno && is_negated_errno(or1k_regs.gpr[11])) {
2308 tcp->u_rval = -1;
2309 u_error = -or1k_regs.gpr[11];
2310 }
2311 else {
2312 tcp->u_rval = or1k_regs.gpr[11];
2313 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002314#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002315 tcp->u_error = u_error;
2316 return 1;
2317}
2318
2319static void
2320dumpio(struct tcb *tcp)
2321{
2322 if (syserror(tcp))
2323 return;
2324 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
2325 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002326 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002327 return;
2328 if (sysent[tcp->scno].sys_func == printargs)
2329 return;
2330 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
2331 if (sysent[tcp->scno].sys_func == sys_read ||
2332 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002333 sysent[tcp->scno].sys_func == sys_recv ||
2334 sysent[tcp->scno].sys_func == sys_recvfrom)
2335 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
2336 else if (sysent[tcp->scno].sys_func == sys_readv)
2337 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2338 return;
2339 }
2340 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
2341 if (sysent[tcp->scno].sys_func == sys_write ||
2342 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002343 sysent[tcp->scno].sys_func == sys_send ||
2344 sysent[tcp->scno].sys_func == sys_sendto)
2345 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
2346 else if (sysent[tcp->scno].sys_func == sys_writev)
2347 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2348 return;
2349 }
2350}
2351
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002352static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002353trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002354{
2355 int sys_res;
2356 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002357 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002358 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002359
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002360 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002361 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002362 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002363
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002364#if SUPPORTED_PERSONALITIES > 1
2365 update_personality(tcp, tcp->currpers);
2366#endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002367 res = (get_regs_error ? -1 : get_syscall_result(tcp));
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002368 if (res == 1) {
2369 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01002370 res = get_error(tcp); /* returns 1 or -1 */
2371 if (res == 1) {
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01002372 if (need_fork_exec_workarounds)
2373 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01002374 if (filtered(tcp)) {
2375 goto ret;
2376 }
2377 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002378 }
2379
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002380 if (cflag) {
2381 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002382 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002383 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002384 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002385 }
2386 }
2387
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002388 /* If not in -ff mode, and printing_tcp != tcp,
2389 * then the log currently does not end with output
2390 * of _our syscall entry_, but with something else.
2391 * We need to say which syscall's return is this.
2392 *
2393 * Forced reprinting via TCB_REPRINT is used only by
2394 * "strace -ff -oLOG test/threaded_execve" corner case.
2395 * It's the only case when -ff mode needs reprinting.
2396 */
2397 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2398 tcp->flags &= ~TCB_REPRINT;
2399 printleader(tcp);
2400 if (!SCNO_IN_RANGE(tcp->scno))
2401 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2402 else
2403 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2404 }
2405 printing_tcp = tcp;
2406
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002407 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002408 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002409 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002410 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002411 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002412 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002413 tcp->flags &= ~TCB_INSYSCALL;
2414 return res;
2415 }
2416
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002417 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002418 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002419 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002420 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002421 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002422 /* FIXME: not_failing_only (IOW, option -z) is broken:
2423 * failure of syscall is known only after syscall return.
2424 * Thus we end up with something like this on, say, ENOENT:
2425 * open("doesnt_exist", O_RDONLY <unfinished ...>
2426 * {next syscall decode}
2427 * whereas the intended result is that open(...) line
2428 * is not shown at all.
2429 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002430 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002431 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002432 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2433 }
2434
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002435 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002436 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002437 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002438 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002439 qual_flags[tcp->scno] & QUAL_RAW) {
2440 if (u_error)
2441 tprintf("= -1 (errno %ld)", u_error);
2442 else
2443 tprintf("= %#lx", tcp->u_rval);
2444 }
2445 else if (!(sys_res & RVAL_NONE) && u_error) {
2446 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002447 /* Blocked signals do not interrupt any syscalls.
2448 * In this case syscalls don't return ERESTARTfoo codes.
2449 *
2450 * Deadly signals set to SIG_DFL interrupt syscalls
2451 * and kill the process regardless of which of the codes below
2452 * is returned by the interrupted syscall.
2453 * In some cases, kernel forces a kernel-generated deadly
2454 * signal to be unblocked and set to SIG_DFL (and thus cause
2455 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2456 * or SIGILL. (The alternative is to leave process spinning
2457 * forever on the faulty instruction - not useful).
2458 *
2459 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2460 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2461 * but kernel will always restart them.
2462 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002463 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002464 /* Most common type of signal-interrupted syscall exit code.
2465 * The system call will be restarted with the same arguments
2466 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2467 */
2468 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002469 break;
2470 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002471 /* Rare. For example, fork() returns this if interrupted.
2472 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2473 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002474 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002475 break;
2476 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002477 /* pause(), rt_sigsuspend() etc use this code.
2478 * SA_RESTART is ignored (assumed not set):
2479 * syscall won't restart (will return EINTR instead)
2480 * even after signal with SA_RESTART set.
2481 * However, after SIG_IGN or SIG_DFL signal it will.
2482 */
2483 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002484 break;
2485 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002486 /* Syscalls like nanosleep(), poll() which can't be
2487 * restarted with their original arguments use this
2488 * code. Kernel will execute restart_syscall() instead,
2489 * which changes arguments before restarting syscall.
2490 * SA_RESTART is ignored (assumed not set) similarly
2491 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2492 * since restart data is saved in "restart block"
2493 * in task struct, and if signal handler uses a syscall
2494 * which in turn saves another such restart block,
2495 * old data is lost and restart becomes impossible)
2496 */
2497 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002498 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002499 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002500 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002501 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002502 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002503 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002504 strerror(u_error));
2505 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002506 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002507 strerror(u_error));
2508 break;
2509 }
2510 if ((sys_res & RVAL_STR) && tcp->auxstr)
2511 tprintf(" (%s)", tcp->auxstr);
2512 }
2513 else {
2514 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002515 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002516 else {
2517 switch (sys_res & RVAL_MASK) {
2518 case RVAL_HEX:
2519 tprintf("= %#lx", tcp->u_rval);
2520 break;
2521 case RVAL_OCTAL:
2522 tprintf("= %#lo", tcp->u_rval);
2523 break;
2524 case RVAL_UDECIMAL:
2525 tprintf("= %lu", tcp->u_rval);
2526 break;
2527 case RVAL_DECIMAL:
2528 tprintf("= %ld", tcp->u_rval);
2529 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002530#if defined(LINUX_MIPSN32) || defined(X32)
2531 /*
2532 case RVAL_LHEX:
2533 tprintf("= %#llx", tcp->u_lrval);
2534 break;
2535 case RVAL_LOCTAL:
2536 tprintf("= %#llo", tcp->u_lrval);
2537 break;
2538 */
2539 case RVAL_LUDECIMAL:
2540 tprintf("= %llu", tcp->u_lrval);
2541 break;
2542 /*
2543 case RVAL_LDECIMAL:
2544 tprintf("= %lld", tcp->u_lrval);
2545 break;
2546 */
2547#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002548 default:
2549 fprintf(stderr,
2550 "invalid rval format\n");
2551 break;
2552 }
2553 }
2554 if ((sys_res & RVAL_STR) && tcp->auxstr)
2555 tprintf(" (%s)", tcp->auxstr);
2556 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002557 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002558 tv_sub(&tv, &tv, &tcp->etime);
2559 tprintf(" <%ld.%06ld>",
2560 (long) tv.tv_sec, (long) tv.tv_usec);
2561 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002562 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002563 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002564 line_ended();
2565
Denys Vlasenko3b738812011-08-22 02:06:35 +02002566 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002567 tcp->flags &= ~TCB_INSYSCALL;
2568 return 0;
2569}
2570
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002571int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002572trace_syscall(struct tcb *tcp)
2573{
2574 return exiting(tcp) ?
2575 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2576}