blob: 7e5cff0cfc74f6277fe39568f25389218e44ff3d [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 Vlasenkoeec8d5d2013-02-14 03:29:48 +0100917 /* PTRACE_GETREGSET was introduced around 2.6.25 */
918 if (os_release >= KERNEL_VERSION(2,6,30)) {
919 /*x86_io.iov_base = &x86_regs_union; - already is */
920 x86_io.iov_len = sizeof(x86_regs_union);
921 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (long) &x86_io);
922 } else {
923 /* Use old method, with heuristical detection of 32-bitness */
924 x86_io.iov_len = sizeof(x86_64_regs);
925 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &x86_64_regs);
926 if (!get_regs_error && x86_64_regs.cs == 0x23) {
927 x86_io.iov_len = sizeof(i386_regs);
928 /*
929 * The order is important: i386_regs and x86_64_regs
930 * are overlaid in memory!
931 */
932 i386_regs.ebx = x86_64_regs.rbx;
933 i386_regs.ecx = x86_64_regs.rcx;
934 i386_regs.edx = x86_64_regs.rdx;
935 i386_regs.esi = x86_64_regs.rsi;
936 i386_regs.edi = x86_64_regs.rdi;
937 i386_regs.ebp = x86_64_regs.rbp;
938 i386_regs.eax = x86_64_regs.rax;
939 /*i386_regs.xds = x86_64_regs.ds; unused by strace */
940 /*i386_regs.xes = x86_64_regs.es; ditto... */
941 /*i386_regs.xfs = x86_64_regs.fs;*/
942 /*i386_regs.xgs = x86_64_regs.gs;*/
943 i386_regs.orig_eax = x86_64_regs.orig_rax;
944 i386_regs.eip = x86_64_regs.rip;
945 /*i386_regs.xcs = x86_64_regs.cs;*/
946 /*i386_regs.eflags = x86_64_regs.eflags;*/
947 i386_regs.esp = x86_64_regs.rsp;
948 /*i386_regs.xss = x86_64_regs.ss;*/
949 }
950 }
Denys Vlasenko401374e2013-02-06 18:24:39 +0100951# elif defined(ARM)
952 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (void *)&arm_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100953# elif defined(AARCH64)
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100954 /*aarch64_io.iov_base = &arm_regs_union; - already is */
955 aarch64_io.iov_len = sizeof(arm_regs_union);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100956 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void *)&aarch64_io);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100957# if 0
958 /* Paranoia checks */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100959 if (get_regs_error)
960 return;
961 switch (aarch64_io.iov_len) {
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100962 case sizeof(aarch64_regs):
963 /* We are in 64-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100964 break;
965 case sizeof(arm_regs):
966 /* We are in 32-bit mode */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100967 break;
968 default:
969 get_regs_error = -1;
970 break;
971 }
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100972# endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100973# elif defined(SPARC) || defined(SPARC64)
974 get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&regs, 0);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100975# elif defined(TILE)
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500976 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &tile_regs);
Christian Svensson492f81f2013-02-14 13:26:27 +0100977# elif defined(OR1K)
978 or1k_io.iov_len = sizeof(or1k_regs);
979 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &or1k_io);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100980# endif
981}
982#endif
983
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200984/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100985 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
986 * 1: ok, continue in trace_syscall_entering().
987 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200988 * ("????" etc) and bail out.
989 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100990static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200991get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000992{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000993 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000994
Denys Vlasenko523635f2012-02-25 02:44:25 +0100995#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000996 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200997 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000998
999 if (syscall_mode != -ENOSYS) {
1000 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001001 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +00001002 */
1003 scno = syscall_mode;
1004 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001005 /*
Michal Ludvig882eda82002-11-11 12:50:47 +00001006 * Old style of "passing" the scno via the SVC instruction.
1007 */
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001008 long psw;
Michal Ludvig882eda82002-11-11 12:50:47 +00001009 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001010 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +02001011 static const int gpr_offset[16] = {
1012 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
1013 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
1014 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
1015 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
1016 };
Roland McGrath761b5d72002-12-15 23:58:31 +00001017
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001018 if (upeek(tcp, PT_PSWADDR, &psw) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +00001019 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +00001020 errno = 0;
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001021 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(psw - sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +00001022 if (errno) {
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001023 perror_msg("%s", "peektext(psw-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +00001024 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +00001025 }
Michal Ludvig882eda82002-11-11 12:50:47 +00001026
1027 /*
1028 * We have to check if the SVC got executed directly or via an
1029 * EXECUTE instruction. In case of EXECUTE it is necessary to do
1030 * instruction decoding to derive the system call number.
1031 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
1032 * so that this doesn't work if a SVC opcode is part of an EXECUTE
1033 * opcode. Since there is no way to find out the opcode size this
1034 * is the best we can do...
1035 */
Michal Ludvig882eda82002-11-11 12:50:47 +00001036 if ((opcode & 0xff00) == 0x0a00) {
1037 /* SVC opcode */
1038 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +00001039 }
Michal Ludvig882eda82002-11-11 12:50:47 +00001040 else {
1041 /* SVC got executed by EXECUTE instruction */
1042
1043 /*
1044 * Do instruction decoding of EXECUTE. If you really want to
1045 * understand this, read the Principles of Operations.
1046 */
1047 svc_addr = (void *) (opcode & 0xfff);
1048
1049 tmp = 0;
1050 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001051 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001052 return -1;
1053 svc_addr += tmp;
1054
1055 tmp = 0;
1056 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001057 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001058 return -1;
1059 svc_addr += tmp;
1060
Denys Vlasenkofb036672009-01-23 16:30:26 +00001061 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +00001062 if (errno)
1063 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001064# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +00001065 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001066# else
Michal Ludvig882eda82002-11-11 12:50:47 +00001067 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001068# endif
Michal Ludvig882eda82002-11-11 12:50:47 +00001069 tmp = 0;
1070 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001071 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001072 return -1;
1073
1074 scno = (scno | tmp) & 0xff;
1075 }
1076 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001077#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001078 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001079 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001080# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001081 /* TODO: speed up strace by not doing this at every syscall.
1082 * We only need to do it after execve.
1083 */
1084 int currpers;
1085 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +02001086
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001087 /* Check for 64/32 bit mode. */
1088 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
1089 return -1;
1090 /* SF is bit 0 of MSR */
1091 if (val < 0)
1092 currpers = 0;
1093 else
1094 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001095 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001096# endif
1097#elif defined(AVR32)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001098 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001099#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001100 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001101 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001102#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001103 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +02001104#elif defined(X86_64) || defined(X32)
1105# ifndef __X32_SYSCALL_BIT
1106# define __X32_SYSCALL_BIT 0x40000000
1107# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001108 int currpers;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001109# if 1
1110 /* GETREGSET of NT_PRSTATUS tells us regset size,
1111 * which unambiguously detects i386.
1112 *
1113 * Linux kernel distinguishes x86-64 and x32 processes
1114 * solely by looking at __X32_SYSCALL_BIT:
1115 * arch/x86/include/asm/compat.h::is_x32_task():
1116 * if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)
1117 * return true;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001118 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001119 if (x86_io.iov_len == sizeof(i386_regs)) {
1120 scno = i386_regs.orig_eax;
1121 currpers = 1;
1122 } else {
1123 scno = x86_64_regs.orig_rax;
1124 currpers = 0;
1125 if (scno & __X32_SYSCALL_BIT) {
1126 scno -= __X32_SYSCALL_BIT;
1127 currpers = 2;
1128 }
1129 }
1130# elif 0
1131 /* cs = 0x33 for long mode (native 64 bit and x32)
1132 * cs = 0x23 for compatibility mode (32 bit)
1133 * ds = 0x2b for x32 mode (x86-64 in 32 bit)
1134 */
1135 scno = x86_64_regs.orig_rax;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001136 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001137 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +02001138 case 0x33:
1139 if (x86_64_regs.ds == 0x2b) {
1140 currpers = 2;
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001141 scno &= ~__X32_SYSCALL_BIT;
H.J. Lu35be5812012-04-16 13:00:01 +02001142 } else
1143 currpers = 0;
1144 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001145 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001146 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001147 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001148 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001149 currpers = current_personality;
1150 break;
1151 }
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001152# elif 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001153 /* This version analyzes the opcode of a syscall instruction.
1154 * (int 0x80 on i386 vs. syscall on x86-64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001155 * It works, but is too complicated, and strictly speaking, unreliable.
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001156 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001157 unsigned long call, rip = x86_64_regs.rip;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001158 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
1159 rip -= 2;
1160 errno = 0;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001161 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001162 if (errno)
1163 fprintf(stderr, "ptrace_peektext failed: %s\n",
1164 strerror(errno));
1165 switch (call & 0xffff) {
1166 /* x86-64: syscall = 0x0f 0x05 */
1167 case 0x050f: currpers = 0; break;
1168 /* i386: int 0x80 = 0xcd 0x80 */
1169 case 0x80cd: currpers = 1; break;
1170 default:
1171 currpers = current_personality;
1172 fprintf(stderr,
1173 "Unknown syscall opcode (0x%04X) while "
1174 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001175 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001176 break;
1177 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001178# endif
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001179
H.J. Lu35be5812012-04-16 13:00:01 +02001180# ifdef X32
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001181 /* If we are built for a x32 system, then personality 0 is x32
1182 * (not x86_64), and stracing of x86_64 apps is not supported.
1183 * Stracing of i386 apps is still supported.
H.J. Lu085e4282012-04-17 11:05:04 -07001184 */
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001185 if (currpers == 0) {
1186 fprintf(stderr, "syscall_%lu(...) in unsupported "
1187 "64-bit mode of process PID=%d\n",
1188 scno, tcp->pid);
1189 return 0;
H.J. Lu35be5812012-04-16 13:00:01 +02001190 }
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001191 currpers &= ~2; /* map 2,1 to 0,1 */
H.J. Lu35be5812012-04-16 13:00:01 +02001192# endif
H.J. Lu085e4282012-04-17 11:05:04 -07001193 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001194#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001195# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001196 long psr;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001197 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001198 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001199 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001200 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001201 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001202 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001203 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001204 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001205 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001206#elif defined(AARCH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001207 switch (aarch64_io.iov_len) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001208 case sizeof(aarch64_regs):
1209 /* We are in 64-bit mode */
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001210 scno = aarch64_regs.regs[8];
1211 update_personality(tcp, 1);
1212 break;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001213 case sizeof(arm_regs):
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001214 /* We are in 32-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001215 scno = arm_regs.ARM_r7;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001216 update_personality(tcp, 0);
1217 break;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001218 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001219#elif defined(ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001220 /*
1221 * We only need to grab the syscall number on syscall entry.
1222 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001223 if (arm_regs.ARM_ip == 0) {
Roland McGrath0f87c492003-06-03 23:29:04 +00001224 /*
Denys Vlasenko401374e2013-02-06 18:24:39 +01001225 * Note: we only deal with 32-bit CPUs here
Roland McGrath0f87c492003-06-03 23:29:04 +00001226 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001227 if (arm_regs.ARM_cpsr & 0x20) {
Roland McGrath0f87c492003-06-03 23:29:04 +00001228 /*
1229 * Get the Thumb-mode system call number
1230 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001231 scno = arm_regs.ARM_r7;
Roland McGrath0f87c492003-06-03 23:29:04 +00001232 } else {
1233 /*
1234 * Get the ARM-mode system call number
1235 */
1236 errno = 0;
Denys Vlasenko401374e2013-02-06 18:24:39 +01001237 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(arm_regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +00001238 if (errno)
1239 return -1;
1240
Roland McGrathf691bd22006-04-25 07:34:41 +00001241 /* Handle the EABI syscall convention. We do not
1242 bother converting structures between the two
1243 ABIs, but basic functionality should work even
1244 if strace and the traced program have different
1245 ABIs. */
1246 if (scno == 0xef000000) {
Denys Vlasenko401374e2013-02-06 18:24:39 +01001247 scno = arm_regs.ARM_r7;
Roland McGrathf691bd22006-04-25 07:34:41 +00001248 } else {
1249 if ((scno & 0x0ff00000) != 0x0f900000) {
1250 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1251 scno);
1252 return -1;
1253 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001254
Roland McGrathf691bd22006-04-25 07:34:41 +00001255 /*
1256 * Fixup the syscall number
1257 */
1258 scno &= 0x000fffff;
1259 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001260 }
Roland McGrath56703312008-05-20 01:35:55 +00001261 if (scno & 0x0f0000) {
1262 /*
1263 * Handle ARM specific syscall
1264 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001265 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +00001266 scno &= 0x0000ffff;
1267 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001268 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001269
Roland McGrath0f87c492003-06-03 23:29:04 +00001270 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001271 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1272 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001273 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001274#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001275 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001276 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001277#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001278 unsigned long long regs[38];
1279
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001280 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001281 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001282 mips_a3 = regs[REG_A3];
1283 mips_r2 = regs[REG_V0];
Roland McGrath542c2c62008-05-20 01:11:56 +00001284
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001285 scno = mips_r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001286 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001287 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001288 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001289 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001290 return 0;
1291 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001292 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001293#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001294 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001295 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001296 if (upeek(tcp, REG_V0, &scno) < 0)
1297 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001298
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001299 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001300 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001301 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001302 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001303 return 0;
1304 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001305 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001306#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001307 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001308 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001309 if (upeek(tcp, REG_R0, &scno) < 0)
1310 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001311
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001312 /*
1313 * Do some sanity checks to figure out if it's
1314 * really a syscall entry
1315 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001316 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001317 if (alpha_a3 == 0 || alpha_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001318 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001319 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001320 return 0;
1321 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001322 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001323#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001324 /* Disassemble the syscall trap. */
1325 /* Retrieve the syscall trap instruction. */
Denys Vlasenko46455822013-02-05 17:02:59 +01001326 unsigned long trap;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001327 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001328# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001329 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1330 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001331# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001332 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001333# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001334 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001335 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001336
1337 /* Disassemble the trap to see what personality to use. */
1338 switch (trap) {
1339 case 0x91d02010:
1340 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001341 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001342 break;
1343 case 0x91d0206d:
1344 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001345 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001346 break;
1347 case 0x91d02000:
1348 /* SunOS syscall trap. (pers 1) */
1349 fprintf(stderr, "syscall: SunOS no support\n");
1350 return -1;
1351 case 0x91d02008:
1352 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001353 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001354 break;
1355 case 0x91d02009:
1356 /* NetBSD/FreeBSD syscall trap. */
1357 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1358 return -1;
1359 case 0x91d02027:
1360 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001361 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001362 break;
1363 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001364# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001365 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001366# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001367 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001368# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001369 return -1;
1370 }
1371
1372 /* Extract the system call number from the registers. */
1373 if (trap == 0x91d02027)
1374 scno = 156;
1375 else
1376 scno = regs.u_regs[U_REG_G1];
1377 if (scno == 0) {
1378 scno = regs.u_regs[U_REG_O0];
1379 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1380 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001381#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001382 if (upeek(tcp, PT_GR20, &scno) < 0)
1383 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001384#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001385 /*
1386 * In the new syscall ABI, the system call number is in R3.
1387 */
1388 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1389 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001390
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001391 if (scno < 0) {
1392 /* Odd as it may seem, a glibc bug has been known to cause
1393 glibc to issue bogus negative syscall numbers. So for
1394 our purposes, make strace print what it *should* have been */
1395 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001396 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001397 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001398 "Detected glibc bug: bogus system call"
1399 " number = %ld, correcting to %ld\n",
1400 scno,
1401 correct_scno);
1402 scno = correct_scno;
1403 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001404#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001405 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001406 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001407 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001408#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001409 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1410 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001411#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001412 int currpers;
1413 scno = tile_regs.regs[10];
1414# ifdef __tilepro__
1415 currpers = 1;
1416# else
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001417# ifndef PT_FLAGS_COMPAT
1418# define PT_FLAGS_COMPAT 0x10000 /* from Linux 3.8 on */
1419# endif
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001420 if (tile_regs.flags & PT_FLAGS_COMPAT)
1421 currpers = 1;
1422 else
1423 currpers = 0;
1424# endif
1425 update_personality(tcp, currpers);
1426
1427 if (!(tcp->flags & TCB_INSYSCALL)) {
1428 /* Check if we return from execve. */
1429 if (tcp->flags & TCB_WAITEXECVE) {
1430 tcp->flags &= ~TCB_WAITEXECVE;
1431 return 0;
1432 }
1433 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001434#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001435 if (upeek(tcp, 0, &scno) < 0)
1436 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01001437#elif defined(OR1K)
1438 scno = or1k_regs.gpr[11];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001439#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001440
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001441 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001442 return 1;
1443}
1444
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001445/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001446 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001447 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1448 * 1: ok, continue in trace_syscall_entering().
1449 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001450 * ("????" etc) and bail out.
1451 */
Roland McGratha4d48532005-06-08 20:45:28 +00001452static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001453syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001454{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001455 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001456#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001457 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001458 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001459 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1460 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001461 }
H.J. Lu35be5812012-04-16 13:00:01 +02001462#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001463 {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001464 long rax;
1465 if (x86_io.iov_len == sizeof(i386_regs)) {
1466 /* Sign extend from 32 bits */
1467 rax = (int32_t)i386_regs.eax;
1468 } else {
1469 /* Note: in X32 build, this truncates 64 to 32 bits */
1470 rax = x86_64_regs.rax;
1471 }
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001472 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001473 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001474 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1475 return 0;
1476 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001477 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001478#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001479 /* TODO: we already fetched PT_GPR2 in get_scno
1480 * and stored it in syscall_mode, reuse it here
1481 * instead of re-fetching?
1482 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001483 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001484 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001485 if (syscall_mode != -ENOSYS)
1486 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001487 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001488 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001489 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001490 return 0;
1491 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001492#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001493 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001494 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001495 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001496 if (m68k_d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001497 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001498 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", m68k_d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001499 return 0;
1500 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001501#elif defined(IA64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001502 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001503 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001504 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001505 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001506 if (ia32 && ia64_r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001507 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001508 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", ia64_r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001509 return 0;
1510 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001511#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001512 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001513 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001514 if (cris_r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001515 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001516 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", cris_r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001517 return 0;
1518 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001519#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001520 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001521 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001522 if (microblaze_r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001523 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001524 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", microblaze_r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001525 return 0;
1526 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001527#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001528 return 1;
1529}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001530
Denys Vlasenko146b9442012-03-18 22:10:48 +01001531static void
1532internal_fork(struct tcb *tcp)
1533{
1534#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1535# define ARG_FLAGS 1
1536#else
1537# define ARG_FLAGS 0
1538#endif
1539#ifndef CLONE_UNTRACED
1540# define CLONE_UNTRACED 0x00800000
1541#endif
1542 if ((ptrace_setoptions
1543 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1544 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1545 return;
1546
1547 if (!followfork)
1548 return;
1549
1550 if (entering(tcp)) {
1551 /*
1552 * We won't see the new child if clone is called with
1553 * CLONE_UNTRACED, so we keep the same logic with that option
1554 * and don't trace it.
1555 */
1556 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1557 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1558 return;
1559 setbpt(tcp);
1560 } else {
1561 if (tcp->flags & TCB_BPTSET)
1562 clearbpt(tcp);
1563 }
1564}
1565
1566#if defined(TCB_WAITEXECVE)
1567static void
1568internal_exec(struct tcb *tcp)
1569{
1570 /* Maybe we have post-execve SIGTRAP suppressed? */
1571 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1572 return; /* yes, no need to do anything */
1573
1574 if (exiting(tcp) && syserror(tcp))
1575 /* Error in execve, no post-execve SIGTRAP expected */
1576 tcp->flags &= ~TCB_WAITEXECVE;
1577 else
1578 tcp->flags |= TCB_WAITEXECVE;
1579}
1580#endif
1581
1582static void
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001583syscall_fixup_for_fork_exec(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001584{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001585 /*
1586 * We must always trace a few critical system calls in order to
1587 * correctly support following forks in the presence of tracing
1588 * qualifiers.
1589 */
1590 int (*func)();
1591
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001592 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001593 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001594
1595 func = sysent[tcp->scno].sys_func;
1596
1597 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001598 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001599 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001600 ) {
1601 internal_fork(tcp);
1602 return;
1603 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001604
Denys Vlasenko84703742012-02-25 02:38:52 +01001605#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001606 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001607# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001608 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001609# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001610 ) {
1611 internal_exec(tcp);
1612 return;
1613 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001614#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001615}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001616
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001617/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001618static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001619get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001620{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001621 int i, nargs;
1622
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001623 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001624 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001625 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001626 nargs = tcp->u_nargs = MAX_ARGS;
1627
Denys Vlasenko523635f2012-02-25 02:44:25 +01001628#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001629 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001630 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1631 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001632#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001633 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001634 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1635 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001636#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001637 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001638 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001639 long rbs_end;
1640 /* be backwards compatible with kernel < 2.4.4... */
1641# ifndef PT_RBS_END
1642# define PT_RBS_END PT_AR_BSP
1643# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001644
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001645 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1646 return -1;
1647 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001648 return -1;
1649
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001650 sof = (cfm >> 0) & 0x7f;
1651 sol = (cfm >> 7) & 0x7f;
1652 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1653
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001654 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001655 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1656 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1657 return -1;
1658 }
1659 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001660 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1661 PT_R9 /* ECX = out1 */,
1662 PT_R10 /* EDX = out2 */,
1663 PT_R14 /* ESI = out3 */,
1664 PT_R15 /* EDI = out4 */,
1665 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001666
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001667 for (i = 0; i < nargs; ++i) {
1668 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1669 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001670 /* truncate away IVE sign-extension */
1671 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001672 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001673 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001674#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001675 /* N32 and N64 both use up to six registers. */
1676 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001677
1678 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1679 return -1;
1680
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001681 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001682 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001683# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001684 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001685# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001686 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001687#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001688 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001689 long sp;
1690
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001691 if (upeek(tcp, REG_SP, &sp) < 0)
1692 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001693 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001694 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1695 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001696 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001697 (char *)(tcp->u_arg + 4));
1698 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001699 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001700 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001701 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001702 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001703#elif defined(POWERPC)
1704# ifndef PT_ORIG_R3
1705# define PT_ORIG_R3 34
1706# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001707 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001708 if (upeek(tcp, (i==0) ?
1709 (sizeof(unsigned long) * PT_ORIG_R3) :
1710 ((i+PT_R3) * sizeof(unsigned long)),
1711 &tcp->u_arg[i]) < 0)
1712 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001713 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001714#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001715 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001716 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001717#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001718 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001719 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1720 return -1;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001721#elif defined(ARM) || defined(AARCH64)
1722# if defined(AARCH64)
1723 if (tcp->currpers == 1)
1724 for (i = 0; i < nargs; ++i)
1725 tcp->u_arg[i] = aarch64_regs.regs[i];
1726 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001727# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001728 for (i = 0; i < nargs; ++i)
Denys Vlasenko401374e2013-02-06 18:24:39 +01001729 tcp->u_arg[i] = arm_regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001730#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001731 (void)i;
1732 (void)nargs;
1733 tcp->u_arg[0] = regs.r12;
1734 tcp->u_arg[1] = regs.r11;
1735 tcp->u_arg[2] = regs.r10;
1736 tcp->u_arg[3] = regs.r9;
1737 tcp->u_arg[4] = regs.r5;
1738 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001739#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001740 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 +02001741
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001742 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001743 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1744 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001745#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001746 static const int syscall_regs[MAX_ARGS] = {
1747 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1748 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001749 };
1750
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001751 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001752 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001753 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001754#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001755 int i;
1756 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001757 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001758
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001759 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001760 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1761 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001762#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001763 (void)i;
1764 (void)nargs;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001765 if (x86_io.iov_len != sizeof(i386_regs)) {
1766 /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001767 tcp->u_arg[0] = x86_64_regs.rdi;
1768 tcp->u_arg[1] = x86_64_regs.rsi;
1769 tcp->u_arg[2] = x86_64_regs.rdx;
1770 tcp->u_arg[3] = x86_64_regs.r10;
1771 tcp->u_arg[4] = x86_64_regs.r8;
1772 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001773# ifdef X32
1774 tcp->ext_arg[0] = x86_64_regs.rdi;
1775 tcp->ext_arg[1] = x86_64_regs.rsi;
1776 tcp->ext_arg[2] = x86_64_regs.rdx;
1777 tcp->ext_arg[3] = x86_64_regs.r10;
1778 tcp->ext_arg[4] = x86_64_regs.r8;
1779 tcp->ext_arg[5] = x86_64_regs.r9;
1780# endif
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001781 } else {
1782 /* i386 ABI */
1783 /* Sign-extend from 32 bits */
1784 tcp->u_arg[0] = (long)(int32_t)i386_regs.ebx;
1785 tcp->u_arg[1] = (long)(int32_t)i386_regs.ecx;
1786 tcp->u_arg[2] = (long)(int32_t)i386_regs.edx;
1787 tcp->u_arg[3] = (long)(int32_t)i386_regs.esi;
1788 tcp->u_arg[4] = (long)(int32_t)i386_regs.edi;
1789 tcp->u_arg[5] = (long)(int32_t)i386_regs.ebp;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001790 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001791#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001792 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001793 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1794 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001795#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001796 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001797 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001798 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001799 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001800
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001801 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001802 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1803 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001804#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001805 for (i = 0; i < nargs; ++i)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001806 tcp->u_arg[i] = tile_regs.regs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001807#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001808 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001809 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1810 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001811#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001812 (void)i;
1813 (void)nargs;
1814 tcp->u_arg[0] = i386_regs.ebx;
1815 tcp->u_arg[1] = i386_regs.ecx;
1816 tcp->u_arg[2] = i386_regs.edx;
1817 tcp->u_arg[3] = i386_regs.esi;
1818 tcp->u_arg[4] = i386_regs.edi;
1819 tcp->u_arg[5] = i386_regs.ebp;
Christian Svensson492f81f2013-02-14 13:26:27 +01001820#elif defined(OR1K)
1821 (void)nargs;
1822 for (i = 0; i < 6; ++i)
1823 tcp->u_arg[i] = or1k_regs.gpr[3 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001824#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001825 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001826 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1827 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001828#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001829 return 1;
1830}
1831
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001832static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001833trace_syscall_entering(struct tcb *tcp)
1834{
1835 int res, scno_good;
1836
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001837#if defined TCB_WAITEXECVE
1838 if (tcp->flags & TCB_WAITEXECVE) {
1839 /* This is the post-execve SIGTRAP. */
1840 tcp->flags &= ~TCB_WAITEXECVE;
1841 return 0;
1842 }
1843#endif
1844
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001845 scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001846 if (res == 0)
1847 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001848 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001849 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001850 if (res == 0)
1851 return res;
1852 if (res == 1)
1853 res = get_syscall_args(tcp);
1854 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001855
1856 if (res != 1) {
1857 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001858 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001859 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001860 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001861 tprintf("syscall_%lu(", tcp->scno);
1862 else
1863 tprintf("%s(", sysent[tcp->scno].sys_name);
1864 /*
1865 * " <unavailable>" will be added later by the code which
1866 * detects ptrace errors.
1867 */
1868 goto ret;
1869 }
1870
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001871#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1872 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001873# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001874 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001875 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001876 break;
1877 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001878# endif
1879# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001880 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001881 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001882 break;
1883 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001884# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001885 break;
1886 }
1887#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1888
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001889 if (need_fork_exec_workarounds)
1890 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001891
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001892 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001893 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1894 (tracing_paths && !pathtrace_match(tcp))) {
1895 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1896 return 0;
1897 }
1898
1899 tcp->flags &= ~TCB_FILTERED;
1900
1901 if (cflag == CFLAG_ONLY_STATS) {
1902 res = 0;
1903 goto ret;
1904 }
1905
1906 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001907 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001908 tprintf("syscall_%lu(", tcp->scno);
1909 else
1910 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001911 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001912 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1913 sysent[tcp->scno].sys_func != sys_exit))
1914 res = printargs(tcp);
1915 else
1916 res = (*sysent[tcp->scno].sys_func)(tcp);
1917
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001918 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001919 ret:
1920 tcp->flags |= TCB_INSYSCALL;
1921 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001922 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001923 gettimeofday(&tcp->etime, NULL);
1924 return res;
1925}
1926
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001927/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001928 * 1: ok, continue in trace_syscall_exiting().
1929 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001930 * ("????" etc) and bail out.
1931 */
1932static int
1933get_syscall_result(struct tcb *tcp)
1934{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001935#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001936 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1937 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001938#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001939# define SO_MASK 0x10000000
1940 {
1941 long flags;
1942 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1943 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001944 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001945 return -1;
1946 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001947 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001948 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001949#elif defined(AVR32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001950 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001951#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001952 if (upeek(tcp, PT_R0, &bfin_r0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001953 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001954#elif defined(I386)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001955 /* already done by get_regs */
H.J. Lu35be5812012-04-16 13:00:01 +02001956#elif defined(X86_64) || defined(X32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001957 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001958#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001959# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001960 long psr;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001961 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1962 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001963 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001964 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001965 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001966 return -1;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001967#elif defined(ARM)
1968 /* already done by get_regs */
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001969#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001970 /* register reading already done by get_regs */
1971
1972 /* Used to do this, but we did it on syscall entry already: */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001973 /* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
1974 * else it's personality 0.
1975 */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001976 /*update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));*/
Denys Vlasenko523635f2012-02-25 02:44:25 +01001977#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001978 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001979 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001980#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001981 unsigned long long regs[38];
1982
1983 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1984 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001985 mips_a3 = regs[REG_A3];
1986 mips_r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001987#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001988 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001989 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001990 if (upeek(tcp, REG_V0, &mips_r2) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001991 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001992#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001993 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001994 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001995 if (upeek(tcp, REG_R0, &alpha_r0) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001996 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001997#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001998 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001999#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002000 if (upeek(tcp, PT_GR28, &hppa_r28) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002001 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002002#elif defined(SH)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002003 /* new syscall ABI returns result in R0 */
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002004 if (upeek(tcp, 4*REG_REG0, (long *)&sh_r0) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002005 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002006#elif defined(SH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002007 /* ABI defines result returned in r9 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002008 if (upeek(tcp, REG_GENERAL(9), (long *)&sh64_r9) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002009 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002010#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002011 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002012 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002013#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002014 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002015#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002016 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002017 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01002018#elif defined(OR1K)
2019 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002020#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002021 return 1;
2022}
2023
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002024/* Called at each syscall exit */
2025static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002026syscall_fixup_on_sysexit(struct tcb *tcp)
2027{
Denys Vlasenko523635f2012-02-25 02:44:25 +01002028#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002029 if (syscall_mode != -ENOSYS)
2030 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02002031 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002032 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
2033 /*
2034 * Return from execve.
2035 * Fake a return value of zero. We leave the TCB_WAITEXECVE
2036 * flag set for the post-execve SIGTRAP to see and reset.
2037 */
2038 gpr2 = 0;
2039 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002040#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002041}
2042
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002043/*
2044 * Check the syscall return value register value for whether it is
2045 * a negated errno code indicating an error, or a success return value.
2046 */
2047static inline int
2048is_negated_errno(unsigned long int val)
2049{
2050 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002051#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01002052 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002053 val = (unsigned int) val;
2054 max = (unsigned int) max;
2055 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002056#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002057 return val > max;
2058}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002059
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002060#if defined(X32)
2061static inline int
2062is_negated_errno_x32(unsigned long long val)
2063{
2064 unsigned long long max = -(long long) nerrnos;
2065 /*
2066 * current_wordsize is 4 even in personality 0 (native X32)
2067 * but truncation _must not_ be done in it.
2068 * can't check current_wordsize here!
2069 */
2070 if (current_personality != 0) {
2071 val = (uint32_t) val;
2072 max = (uint32_t) max;
2073 }
2074 return val > max;
2075}
2076#endif
2077
Denys Vlasenko907735a2012-03-21 00:23:16 +01002078/* Returns:
2079 * 1: ok, continue in trace_syscall_exiting().
2080 * -1: error, trace_syscall_exiting() should print error indicator
2081 * ("????" etc) and bail out.
2082 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002083static int
2084get_error(struct tcb *tcp)
2085{
2086 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002087 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002088 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002089 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
2090 check_errno = 0;
2091 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002092#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002093 if (check_errno && is_negated_errno(gpr2)) {
2094 tcp->u_rval = -1;
2095 u_error = -gpr2;
2096 }
2097 else {
2098 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002099 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002100#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002101 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002102 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002103 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002104 }
2105 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002106 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002107 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002108#elif defined(X86_64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002109 long rax;
2110 if (x86_io.iov_len == sizeof(i386_regs)) {
2111 /* Sign extend from 32 bits */
2112 rax = (int32_t)i386_regs.eax;
2113 } else {
2114 rax = x86_64_regs.rax;
2115 }
2116 if (check_errno && is_negated_errno(rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002117 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002118 u_error = -rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002119 }
2120 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002121 tcp->u_rval = rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002122 }
2123#elif defined(X32)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002124 /* In X32, return value is 64-bit (llseek uses one).
2125 * Using merely "long rax" would not work.
2126 */
2127 long long rax;
2128 if (x86_io.iov_len == sizeof(i386_regs)) {
2129 /* Sign extend from 32 bits */
2130 rax = (int32_t)i386_regs.eax;
2131 } else {
2132 rax = x86_64_regs.rax;
2133 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002134 /* Careful: is_negated_errno() works only on longs */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002135 if (check_errno && is_negated_errno_x32(rax)) {
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002136 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002137 u_error = -rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002138 }
2139 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002140 tcp->u_rval = rax; /* truncating */
2141 tcp->u_lrval = rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002142 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002143#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002144 if (ia32) {
2145 int err;
2146
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002147 err = (int)ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002148 if (check_errno && is_negated_errno(err)) {
2149 tcp->u_rval = -1;
2150 u_error = -err;
2151 }
2152 else {
2153 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002154 }
2155 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002156 if (check_errno && ia64_r10) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002157 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002158 u_error = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002159 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002160 tcp->u_rval = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002161 }
2162 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002163#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002164 if (check_errno && mips_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002165 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002166 u_error = mips_r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002167 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002168 tcp->u_rval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002169# if defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002170 tcp->u_lrval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002171# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002172 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002173#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002174 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002175 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002176 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002177 }
2178 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002179 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002180 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002181#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002182 if (check_errno && is_negated_errno(m68k_d0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002183 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002184 u_error = -m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002185 }
2186 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002187 tcp->u_rval = m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002188 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002189#elif defined(ARM) || defined(AARCH64)
2190# if defined(AARCH64)
2191 if (tcp->currpers == 1) {
2192 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2193 tcp->u_rval = -1;
2194 u_error = -aarch64_regs.regs[0];
2195 }
2196 else {
2197 tcp->u_rval = aarch64_regs.regs[0];
2198 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002199 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002200 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01002201# endif
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002202 {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002203 if (check_errno && is_negated_errno(arm_regs.ARM_r0)) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002204 tcp->u_rval = -1;
Denys Vlasenko401374e2013-02-06 18:24:39 +01002205 u_error = -arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002206 }
2207 else {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002208 tcp->u_rval = arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002209 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002210 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002211#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002212 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
2213 tcp->u_rval = -1;
2214 u_error = -regs.r12;
2215 }
2216 else {
2217 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002218 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002219#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002220 if (check_errno && is_negated_errno(bfin_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002221 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002222 u_error = -bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002223 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002224 tcp->u_rval = bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002225 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002226#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002227 if (check_errno && alpha_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002228 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002229 u_error = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002230 }
2231 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002232 tcp->u_rval = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002233 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002234#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002235 if (check_errno && regs.psr & PSR_C) {
2236 tcp->u_rval = -1;
2237 u_error = regs.u_regs[U_REG_O0];
2238 }
2239 else {
2240 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002241 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002242#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002243 if (check_errno && regs.tstate & 0x1100000000UL) {
2244 tcp->u_rval = -1;
2245 u_error = regs.u_regs[U_REG_O0];
2246 }
2247 else {
2248 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002249 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002250#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002251 if (check_errno && is_negated_errno(hppa_r28)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002252 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002253 u_error = -hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002254 }
2255 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002256 tcp->u_rval = hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002257 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002258#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002259 if (check_errno && is_negated_errno(sh_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002260 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002261 u_error = -sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002262 }
2263 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002264 tcp->u_rval = sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002265 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002266#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002267 if (check_errno && is_negated_errno(sh64_r9)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002268 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002269 u_error = -sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002270 }
2271 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002272 tcp->u_rval = sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002273 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002274#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002275 if (check_errno && cris_r10 && (unsigned) -cris_r10 < nerrnos) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002276 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002277 u_error = -cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002278 }
2279 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002280 tcp->u_rval = cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002281 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002282#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002283 /*
2284 * The standard tile calling convention returns the value (or negative
2285 * errno) in r0, and zero (or positive errno) in r1.
2286 * Until at least kernel 3.8, however, the r1 value is not reflected
2287 * in ptregs at this point, so we use r0 here.
2288 */
2289 if (check_errno && is_negated_errno(tile_regs.regs[0])) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002290 tcp->u_rval = -1;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002291 u_error = -tile_regs.regs[0];
2292 } else {
2293 tcp->u_rval = tile_regs.regs[0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002294 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002295#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002296 if (check_errno && is_negated_errno(microblaze_r3)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002297 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002298 u_error = -microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002299 }
2300 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002301 tcp->u_rval = microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002302 }
Christian Svensson492f81f2013-02-14 13:26:27 +01002303#elif defined(OR1K)
2304 if (check_errno && is_negated_errno(or1k_regs.gpr[11])) {
2305 tcp->u_rval = -1;
2306 u_error = -or1k_regs.gpr[11];
2307 }
2308 else {
2309 tcp->u_rval = or1k_regs.gpr[11];
2310 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002311#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002312 tcp->u_error = u_error;
2313 return 1;
2314}
2315
2316static void
2317dumpio(struct tcb *tcp)
2318{
2319 if (syserror(tcp))
2320 return;
2321 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
2322 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002323 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002324 return;
2325 if (sysent[tcp->scno].sys_func == printargs)
2326 return;
2327 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
2328 if (sysent[tcp->scno].sys_func == sys_read ||
2329 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002330 sysent[tcp->scno].sys_func == sys_recv ||
2331 sysent[tcp->scno].sys_func == sys_recvfrom)
2332 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
2333 else if (sysent[tcp->scno].sys_func == sys_readv)
2334 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2335 return;
2336 }
2337 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
2338 if (sysent[tcp->scno].sys_func == sys_write ||
2339 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002340 sysent[tcp->scno].sys_func == sys_send ||
2341 sysent[tcp->scno].sys_func == sys_sendto)
2342 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
2343 else if (sysent[tcp->scno].sys_func == sys_writev)
2344 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2345 return;
2346 }
2347}
2348
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002349static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002350trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002351{
2352 int sys_res;
2353 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002354 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002355 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002356
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002357 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002358 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002359 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002360
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002361#if SUPPORTED_PERSONALITIES > 1
2362 update_personality(tcp, tcp->currpers);
2363#endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002364 res = (get_regs_error ? -1 : get_syscall_result(tcp));
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002365 if (res == 1) {
2366 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01002367 res = get_error(tcp); /* returns 1 or -1 */
2368 if (res == 1) {
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01002369 if (need_fork_exec_workarounds)
2370 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01002371 if (filtered(tcp)) {
2372 goto ret;
2373 }
2374 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002375 }
2376
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002377 if (cflag) {
2378 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002379 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002380 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002381 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002382 }
2383 }
2384
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002385 /* If not in -ff mode, and printing_tcp != tcp,
2386 * then the log currently does not end with output
2387 * of _our syscall entry_, but with something else.
2388 * We need to say which syscall's return is this.
2389 *
2390 * Forced reprinting via TCB_REPRINT is used only by
2391 * "strace -ff -oLOG test/threaded_execve" corner case.
2392 * It's the only case when -ff mode needs reprinting.
2393 */
2394 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2395 tcp->flags &= ~TCB_REPRINT;
2396 printleader(tcp);
2397 if (!SCNO_IN_RANGE(tcp->scno))
2398 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2399 else
2400 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2401 }
2402 printing_tcp = tcp;
2403
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002404 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002405 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002406 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002407 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002408 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002409 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002410 tcp->flags &= ~TCB_INSYSCALL;
2411 return res;
2412 }
2413
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002414 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002415 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002416 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002417 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002418 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002419 /* FIXME: not_failing_only (IOW, option -z) is broken:
2420 * failure of syscall is known only after syscall return.
2421 * Thus we end up with something like this on, say, ENOENT:
2422 * open("doesnt_exist", O_RDONLY <unfinished ...>
2423 * {next syscall decode}
2424 * whereas the intended result is that open(...) line
2425 * is not shown at all.
2426 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002427 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002428 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002429 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2430 }
2431
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002432 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002433 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002434 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002435 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002436 qual_flags[tcp->scno] & QUAL_RAW) {
2437 if (u_error)
2438 tprintf("= -1 (errno %ld)", u_error);
2439 else
2440 tprintf("= %#lx", tcp->u_rval);
2441 }
2442 else if (!(sys_res & RVAL_NONE) && u_error) {
2443 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002444 /* Blocked signals do not interrupt any syscalls.
2445 * In this case syscalls don't return ERESTARTfoo codes.
2446 *
2447 * Deadly signals set to SIG_DFL interrupt syscalls
2448 * and kill the process regardless of which of the codes below
2449 * is returned by the interrupted syscall.
2450 * In some cases, kernel forces a kernel-generated deadly
2451 * signal to be unblocked and set to SIG_DFL (and thus cause
2452 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2453 * or SIGILL. (The alternative is to leave process spinning
2454 * forever on the faulty instruction - not useful).
2455 *
2456 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2457 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2458 * but kernel will always restart them.
2459 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002460 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002461 /* Most common type of signal-interrupted syscall exit code.
2462 * The system call will be restarted with the same arguments
2463 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2464 */
2465 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002466 break;
2467 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002468 /* Rare. For example, fork() returns this if interrupted.
2469 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2470 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002471 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002472 break;
2473 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002474 /* pause(), rt_sigsuspend() etc use this code.
2475 * SA_RESTART is ignored (assumed not set):
2476 * syscall won't restart (will return EINTR instead)
2477 * even after signal with SA_RESTART set.
2478 * However, after SIG_IGN or SIG_DFL signal it will.
2479 */
2480 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002481 break;
2482 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002483 /* Syscalls like nanosleep(), poll() which can't be
2484 * restarted with their original arguments use this
2485 * code. Kernel will execute restart_syscall() instead,
2486 * which changes arguments before restarting syscall.
2487 * SA_RESTART is ignored (assumed not set) similarly
2488 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2489 * since restart data is saved in "restart block"
2490 * in task struct, and if signal handler uses a syscall
2491 * which in turn saves another such restart block,
2492 * old data is lost and restart becomes impossible)
2493 */
2494 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002495 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002496 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002497 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002498 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002499 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002500 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002501 strerror(u_error));
2502 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002503 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002504 strerror(u_error));
2505 break;
2506 }
2507 if ((sys_res & RVAL_STR) && tcp->auxstr)
2508 tprintf(" (%s)", tcp->auxstr);
2509 }
2510 else {
2511 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002512 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002513 else {
2514 switch (sys_res & RVAL_MASK) {
2515 case RVAL_HEX:
2516 tprintf("= %#lx", tcp->u_rval);
2517 break;
2518 case RVAL_OCTAL:
2519 tprintf("= %#lo", tcp->u_rval);
2520 break;
2521 case RVAL_UDECIMAL:
2522 tprintf("= %lu", tcp->u_rval);
2523 break;
2524 case RVAL_DECIMAL:
2525 tprintf("= %ld", tcp->u_rval);
2526 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002527#if defined(LINUX_MIPSN32) || defined(X32)
2528 /*
2529 case RVAL_LHEX:
2530 tprintf("= %#llx", tcp->u_lrval);
2531 break;
2532 case RVAL_LOCTAL:
2533 tprintf("= %#llo", tcp->u_lrval);
2534 break;
2535 */
2536 case RVAL_LUDECIMAL:
2537 tprintf("= %llu", tcp->u_lrval);
2538 break;
2539 /*
2540 case RVAL_LDECIMAL:
2541 tprintf("= %lld", tcp->u_lrval);
2542 break;
2543 */
2544#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002545 default:
2546 fprintf(stderr,
2547 "invalid rval format\n");
2548 break;
2549 }
2550 }
2551 if ((sys_res & RVAL_STR) && tcp->auxstr)
2552 tprintf(" (%s)", tcp->auxstr);
2553 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002554 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002555 tv_sub(&tv, &tv, &tcp->etime);
2556 tprintf(" <%ld.%06ld>",
2557 (long) tv.tv_sec, (long) tv.tv_usec);
2558 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002559 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002560 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002561 line_ended();
2562
Denys Vlasenko3b738812011-08-22 02:06:35 +02002563 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002564 tcp->flags &= ~TCB_INSYSCALL;
2565 return 0;
2566}
2567
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002568int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002569trace_syscall(struct tcb *tcp)
2570{
2571 return exiting(tcp) ?
2572 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2573}