blob: 7ed0bdcdb98c5377ea1744e70571fdbbbf90c346 [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
Denys Vlasenkoae8643e2013-02-15 14:55:14 +0100217unsigned current_personality;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000218
Denys Vlasenkoae8643e2013-02-15 14:55:14 +0100219# ifndef current_wordsize
220unsigned current_wordsize;
221static const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000222 PERSONALITY0_WORDSIZE,
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000223 PERSONALITY1_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100224# if SUPPORTED_PERSONALITIES > 2
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000225 PERSONALITY2_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100226# endif
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200227};
Denys Vlasenkoae8643e2013-02-15 14:55:14 +0100228# endif
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000229
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200230void
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000231set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000232{
233 switch (personality) {
234 case 0:
235 errnoent = errnoent0;
236 nerrnos = nerrnos0;
237 sysent = sysent0;
238 nsyscalls = nsyscalls0;
239 ioctlent = ioctlent0;
240 nioctlents = nioctlents0;
241 signalent = signalent0;
242 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000243 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000244 break;
245
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000246 case 1:
247 errnoent = errnoent1;
248 nerrnos = nerrnos1;
249 sysent = sysent1;
250 nsyscalls = nsyscalls1;
251 ioctlent = ioctlent1;
252 nioctlents = nioctlents1;
253 signalent = signalent1;
254 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000255 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000256 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000257
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100258# if SUPPORTED_PERSONALITIES >= 3
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000259 case 2:
260 errnoent = errnoent2;
261 nerrnos = nerrnos2;
262 sysent = sysent2;
263 nsyscalls = nsyscalls2;
264 ioctlent = ioctlent2;
265 nioctlents = nioctlents2;
266 signalent = signalent2;
267 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000268 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000269 break;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100270# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000271 }
272
273 current_personality = personality;
Denys Vlasenkoae8643e2013-02-15 14:55:14 +0100274# ifndef current_wordsize
275 current_wordsize = personality_wordsize[personality];
276# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000277}
278
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000279static void
280update_personality(struct tcb *tcp, int personality)
281{
282 if (personality == current_personality)
283 return;
284 set_personality(personality);
285
286 if (personality == tcp->currpers)
287 return;
288 tcp->currpers = personality;
289
H.J. Lu35be5812012-04-16 13:00:01 +0200290# if defined(POWERPC64)
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000291 if (!qflag) {
292 static const char *const names[] = {"64 bit", "32 bit"};
293 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
294 tcp->pid, names[personality]);
295 }
H.J. Lu35be5812012-04-16 13:00:01 +0200296# elif defined(X86_64)
297 if (!qflag) {
298 static const char *const names[] = {"64 bit", "32 bit", "x32"};
299 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
300 tcp->pid, names[personality]);
301 }
H.J. Lu085e4282012-04-17 11:05:04 -0700302# elif defined(X32)
303 if (!qflag) {
304 static const char *const names[] = {"x32", "32 bit"};
305 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
306 tcp->pid, names[personality]);
307 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000308# elif defined(AARCH64)
309 if (!qflag) {
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100310 static const char *const names[] = {"32-bit", "AArch64"};
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000311 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
312 tcp->pid, names[personality]);
313 }
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100314# elif defined(TILE)
315 if (!qflag) {
316 static const char *const names[] = {"64-bit", "32-bit"};
317 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
318 tcp->pid, names[personality]);
319 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100320# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000321}
322#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000323
Roland McGrath9797ceb2002-12-30 10:23:00 +0000324static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000325
Roland McGrathe10e62a2004-09-04 04:20:43 +0000326static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000327 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000328 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000329 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000330 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000331} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000332 { QUAL_TRACE, "trace", qual_syscall, "system call" },
333 { QUAL_TRACE, "t", qual_syscall, "system call" },
334 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
335 { QUAL_ABBREV, "a", qual_syscall, "system call" },
336 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
337 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
338 { QUAL_RAW, "raw", qual_syscall, "system call" },
339 { QUAL_RAW, "x", qual_syscall, "system call" },
340 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
341 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
342 { QUAL_SIGNAL, "s", qual_signal, "signal" },
343 { QUAL_FAULT, "fault", qual_fault, "fault" },
344 { QUAL_FAULT, "faults", qual_fault, "fault" },
345 { QUAL_FAULT, "m", qual_fault, "fault" },
346 { QUAL_READ, "read", qual_desc, "descriptor" },
347 { QUAL_READ, "reads", qual_desc, "descriptor" },
348 { QUAL_READ, "r", qual_desc, "descriptor" },
349 { QUAL_WRITE, "write", qual_desc, "descriptor" },
350 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
351 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000352 { 0, NULL, NULL, NULL },
353};
354
Roland McGrath9797ceb2002-12-30 10:23:00 +0000355static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000356qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000357{
Roland McGrath138c6a32006-01-12 09:50:49 +0000358 if (pers == 0 || pers < 0) {
359 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000360 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000361 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000362 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000363 }
364
365#if SUPPORTED_PERSONALITIES >= 2
366 if (pers == 1 || pers < 0) {
367 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000368 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000369 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000370 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000371 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100372#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000373
374#if SUPPORTED_PERSONALITIES >= 3
375 if (pers == 2 || pers < 0) {
376 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000377 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000378 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000379 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000380 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100381#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000382}
383
384static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000385qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000386{
387 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000388 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000389
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100390 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000391 int i = string_to_uint(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000392 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000393 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000394 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000395 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000396 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000397 for (i = 0; i < nsyscalls0; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000398 if (sysent0[i].sys_name &&
399 strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000400 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000401 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000402 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000403
404#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000405 for (i = 0; i < nsyscalls1; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000406 if (sysent1[i].sys_name &&
407 strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000408 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000409 rc = 0;
410 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100411#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000412
413#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000414 for (i = 0; i < nsyscalls2; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000415 if (sysent2[i].sys_name &&
416 strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000417 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000418 rc = 0;
419 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100420#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000421
Roland McGrathfe6b3522005-02-02 04:40:11 +0000422 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000423}
424
425static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000426qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000427{
428 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000429
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100430 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000431 int signo = string_to_uint(s);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000432 if (signo < 0 || signo >= MAX_QUALS)
433 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000434 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000435 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000436 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000437 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000438 s += 3;
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100439 for (i = 0; i <= NSIG; i++) {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000440 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000441 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000442 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000443 }
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100444 }
Roland McGrath76421df2005-02-02 03:51:18 +0000445 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000446}
447
448static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000449qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000450{
451 return -1;
452}
453
454static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000455qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000456{
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100457 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000458 int desc = string_to_uint(s);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000459 if (desc < 0 || desc >= MAX_QUALS)
460 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000461 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000462 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000463 }
464 return -1;
465}
466
467static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000468lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000469{
470 if (strcmp(s, "file") == 0)
471 return TRACE_FILE;
472 if (strcmp(s, "ipc") == 0)
473 return TRACE_IPC;
474 if (strcmp(s, "network") == 0)
475 return TRACE_NETWORK;
476 if (strcmp(s, "process") == 0)
477 return TRACE_PROCESS;
478 if (strcmp(s, "signal") == 0)
479 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000480 if (strcmp(s, "desc") == 0)
481 return TRACE_DESC;
Namhyung Kim96792962012-10-24 11:41:57 +0900482 if (strcmp(s, "memory") == 0)
483 return TRACE_MEMORY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000484 return -1;
485}
486
487void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000488qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000489{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000490 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000491 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000492 char *copy;
493 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000494 int i, n;
495
496 opt = &qual_options[0];
497 for (i = 0; (p = qual_options[i].option_name); i++) {
498 n = strlen(p);
499 if (strncmp(s, p, n) == 0 && s[n] == '=') {
500 opt = &qual_options[i];
501 s += n + 1;
502 break;
503 }
504 }
505 not = 0;
506 if (*s == '!') {
507 not = 1;
508 s++;
509 }
510 if (strcmp(s, "none") == 0) {
511 not = 1 - not;
512 s = "all";
513 }
514 if (strcmp(s, "all") == 0) {
515 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000516 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000517 }
518 return;
519 }
520 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000521 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000522 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200523 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200524 if (!copy)
525 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000526 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000527 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000528 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000529 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000530 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000531
532#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000533 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000534 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000535 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100536#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000537
538#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000539 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000540 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000541 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100542#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000543
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000544 continue;
545 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000546 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100547 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000548 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000549 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000550 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000551 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000552 return;
553}
554
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000555#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000556static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000557decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000558{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000559 unsigned long addr;
560 unsigned int i, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000561
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000562 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
563 return;
564
565 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
566 addr = tcp->u_arg[1];
567 tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100568 size = current_wordsize;
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000569 for (i = 0; i < tcp->u_nargs; ++i) {
570 if (size == sizeof(int)) {
571 unsigned int arg;
572 if (umove(tcp, addr, &arg) < 0)
573 arg = 0;
574 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000575 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000576 else {
577 unsigned long arg;
578 if (umove(tcp, addr, &arg) < 0)
579 arg = 0;
580 tcp->u_arg[i] = arg;
581 }
582 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000583 }
584}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000585#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400586
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000587#ifdef SYS_ipc_subcall
588static void
589decode_ipc_subcall(struct tcb *tcp)
590{
591 unsigned int i;
592
593 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
594 return;
595
596 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
597 tcp->u_nargs = sysent[tcp->scno].nargs;
598 for (i = 0; i < tcp->u_nargs; i++)
599 tcp->u_arg[i] = tcp->u_arg[i + 1];
600}
601#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000602
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200603int
604printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000605{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200606 if (entering(tcp)) {
607 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000608
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200609 for (i = 0; i < tcp->u_nargs; i++)
610 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
611 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000612 return 0;
613}
614
Denys Vlasenko72879c62012-02-27 14:18:02 +0100615int
616printargs_lu(struct tcb *tcp)
617{
618 if (entering(tcp)) {
619 int i;
620
621 for (i = 0; i < tcp->u_nargs; i++)
622 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
623 }
624 return 0;
625}
626
627int
628printargs_ld(struct tcb *tcp)
629{
630 if (entering(tcp)) {
631 int i;
632
633 for (i = 0; i < tcp->u_nargs; i++)
634 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
635 }
636 return 0;
637}
638
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100639#if defined(SPARC) || defined(SPARC64) || defined(IA64) || defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200640long
641getrval2(struct tcb *tcp)
642{
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100643 long val;
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200644
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100645# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200646 val = regs.u_regs[U_REG_O1];
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100647# elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200648 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
649 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100650# elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200651 if (upeek(tcp, PT_R9, &val) < 0)
652 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100653# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200654
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200655 return val;
656}
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100657#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200658
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200659int
660is_restart_error(struct tcb *tcp)
661{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200662 switch (tcp->u_error) {
663 case ERESTARTSYS:
664 case ERESTARTNOINTR:
665 case ERESTARTNOHAND:
666 case ERESTART_RESTARTBLOCK:
667 return 1;
668 default:
669 break;
670 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200671 return 0;
672}
673
Denys Vlasenko523635f2012-02-25 02:44:25 +0100674#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100675struct pt_regs i386_regs;
H.J. Lu35be5812012-04-16 13:00:01 +0200676#elif defined(X86_64) || defined(X32)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100677/*
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100678 * On i386, pt_regs and user_regs_struct are the same,
679 * but on 64 bit x86, user_regs_struct has six more fields:
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100680 * fs_base, gs_base, ds, es, fs, gs.
681 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
682 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100683struct i386_user_regs_struct {
684 uint32_t ebx;
685 uint32_t ecx;
686 uint32_t edx;
687 uint32_t esi;
688 uint32_t edi;
689 uint32_t ebp;
690 uint32_t eax;
691 uint32_t xds;
692 uint32_t xes;
693 uint32_t xfs;
694 uint32_t xgs;
695 uint32_t orig_eax;
696 uint32_t eip;
697 uint32_t xcs;
698 uint32_t eflags;
699 uint32_t esp;
700 uint32_t xss;
701};
702static union {
703 struct user_regs_struct x86_64_r;
704 struct i386_user_regs_struct i386_r;
705} x86_regs_union;
706# define x86_64_regs x86_regs_union.x86_64_r
707# define i386_regs x86_regs_union.i386_r
708static struct iovec x86_io = {
709 .iov_base = &x86_regs_union
710};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100711#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200712long ia32 = 0; /* not static */
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100713static long ia64_r8, ia64_r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100714#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +0100715static long ppc_result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100716#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100717static long m68k_d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100718#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100719static long bfin_r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100720#elif defined(ARM)
Denys Vlasenko401374e2013-02-06 18:24:39 +0100721struct pt_regs arm_regs; /* not static */
Steve McIntyred8d3bd32012-10-24 17:58:16 +0100722#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100723static union {
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100724 struct user_pt_regs aarch64_r;
725 struct arm_pt_regs arm_r;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100726} arm_regs_union;
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100727# define aarch64_regs arm_regs_union.aarch64_r
728# define arm_regs arm_regs_union.arm_r
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100729static struct iovec aarch64_io = {
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100730 .iov_base = &arm_regs_union
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100731};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100732#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100733static long alpha_r0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100734static long alpha_a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100735#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200736static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100737#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100738struct pt_regs regs; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100739#elif defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100740static long long mips_a3;
741static long long mips_r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100742#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100743static long mips_a3;
744static long mips_r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100745#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200746static long gpr2;
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200747static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100748#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100749static long hppa_r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100750#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100751static long sh_r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100752#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100753static long sh64_r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100754#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100755static long cris_r10;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100756#elif defined(TILE)
757struct pt_regs tile_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100758#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100759static long microblaze_r3;
Christian Svensson492f81f2013-02-14 13:26:27 +0100760#elif defined(OR1K)
761static struct user_regs_struct or1k_regs;
762static struct iovec or1k_io = {
763 .iov_base = &or1k_regs
764};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100765#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000766
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100767void
768printcall(struct tcb *tcp)
769{
770#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
771 sizeof(long) == 8 ? "[????????????????] " : \
772 NULL /* crash */)
773 if (get_regs_error) {
774 PRINTBADPC;
775 return;
776 }
777#if defined(I386)
778 tprintf("[%08lx] ", i386_regs.eip);
779#elif defined(S390) || defined(S390X)
780 long psw;
781 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
782 PRINTBADPC;
783 return;
784 }
785# ifdef S390
786 tprintf("[%08lx] ", psw);
787# elif S390X
Dmitry V. Levinddba73e2013-02-05 19:01:58 +0000788 tprintf("[%016lx] ", psw);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100789# endif
790#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100791 if (x86_io.iov_len == sizeof(i386_regs)) {
792 tprintf("[%08x] ", (unsigned) i386_regs.eip);
793 } else {
794# if defined(X86_64)
795 tprintf("[%016lx] ", (unsigned long) x86_64_regs.rip);
796# elif defined(X32)
797 /* Note: this truncates 64-bit rip to 32 bits */
798 tprintf("[%08lx] ", (unsigned long) x86_64_regs.rip);
799# endif
800 }
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100801#elif defined(IA64)
802 long ip;
803
804 if (upeek(tcp, PT_B0, &ip) < 0) {
805 PRINTBADPC;
806 return;
807 }
808 tprintf("[%08lx] ", ip);
809#elif defined(POWERPC)
810 long pc;
811
812 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
813 PRINTBADPC;
814 return;
815 }
816# ifdef POWERPC64
817 tprintf("[%016lx] ", pc);
818# else
819 tprintf("[%08lx] ", pc);
820# endif
821#elif defined(M68K)
822 long pc;
823
824 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
825 tprints("[????????] ");
826 return;
827 }
828 tprintf("[%08lx] ", pc);
829#elif defined(ALPHA)
830 long pc;
831
832 if (upeek(tcp, REG_PC, &pc) < 0) {
833 tprints("[????????????????] ");
834 return;
835 }
836 tprintf("[%08lx] ", pc);
837#elif defined(SPARC)
838 tprintf("[%08lx] ", regs.pc);
839#elif defined(SPARC64)
840 tprintf("[%08lx] ", regs.tpc);
841#elif defined(HPPA)
842 long pc;
843
844 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
845 tprints("[????????] ");
846 return;
847 }
848 tprintf("[%08lx] ", pc);
849#elif defined(MIPS)
850 long pc;
851
852 if (upeek(tcp, REG_EPC, &pc) < 0) {
853 tprints("[????????] ");
854 return;
855 }
856 tprintf("[%08lx] ", pc);
857#elif defined(SH)
858 long pc;
859
860 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
861 tprints("[????????] ");
862 return;
863 }
864 tprintf("[%08lx] ", pc);
865#elif defined(SH64)
866 long pc;
867
868 if (upeek(tcp, REG_PC, &pc) < 0) {
869 tprints("[????????????????] ");
870 return;
871 }
872 tprintf("[%08lx] ", pc);
873#elif defined(ARM)
Denys Vlasenko401374e2013-02-06 18:24:39 +0100874 tprintf("[%08lx] ", arm_regs.ARM_pc);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100875#elif defined(AARCH64)
876 /* tprintf("[%016lx] ", aarch64_regs.regs[???]); */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100877#elif defined(AVR32)
878 tprintf("[%08lx] ", regs.pc);
879#elif defined(BFIN)
880 long pc;
881
882 if (upeek(tcp, PT_PC, &pc) < 0) {
883 PRINTBADPC;
884 return;
885 }
886 tprintf("[%08lx] ", pc);
887#elif defined(CRISV10)
888 long pc;
889
890 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
891 PRINTBADPC;
892 return;
893 }
894 tprintf("[%08lx] ", pc);
895#elif defined(CRISV32)
896 long pc;
897
898 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
899 PRINTBADPC;
900 return;
901 }
902 tprintf("[%08lx] ", pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100903#elif defined(TILE)
904# ifdef _LP64
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500905 tprintf("[%016lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100906# else
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500907 tprintf("[%08lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100908# endif
Christian Svensson492f81f2013-02-14 13:26:27 +0100909#elif defined(OR1K)
910 tprintf("[%08lx] ", or1k_regs.pc);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100911#endif /* architecture */
912}
913
914#ifndef get_regs
915long get_regs_error;
916void get_regs(pid_t pid)
917{
918# if defined(AVR32)
919 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
920# elif defined(I386)
921 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &i386_regs);
922# elif defined(X86_64) || defined(X32)
Denys Vlasenkoe3b248d2013-02-15 00:24:19 +0100923 /*
924 * PTRACE_GETREGSET was introduced in 2.6.33.
925 * Let's be paranoid and require a bit later kernel.
926 */
927 if (os_release >= KERNEL_VERSION(2,6,35)) {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100928 /*x86_io.iov_base = &x86_regs_union; - already is */
929 x86_io.iov_len = sizeof(x86_regs_union);
930 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (long) &x86_io);
931 } else {
932 /* Use old method, with heuristical detection of 32-bitness */
933 x86_io.iov_len = sizeof(x86_64_regs);
934 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &x86_64_regs);
935 if (!get_regs_error && x86_64_regs.cs == 0x23) {
936 x86_io.iov_len = sizeof(i386_regs);
937 /*
938 * The order is important: i386_regs and x86_64_regs
939 * are overlaid in memory!
940 */
941 i386_regs.ebx = x86_64_regs.rbx;
942 i386_regs.ecx = x86_64_regs.rcx;
943 i386_regs.edx = x86_64_regs.rdx;
944 i386_regs.esi = x86_64_regs.rsi;
945 i386_regs.edi = x86_64_regs.rdi;
946 i386_regs.ebp = x86_64_regs.rbp;
947 i386_regs.eax = x86_64_regs.rax;
948 /*i386_regs.xds = x86_64_regs.ds; unused by strace */
949 /*i386_regs.xes = x86_64_regs.es; ditto... */
950 /*i386_regs.xfs = x86_64_regs.fs;*/
951 /*i386_regs.xgs = x86_64_regs.gs;*/
952 i386_regs.orig_eax = x86_64_regs.orig_rax;
953 i386_regs.eip = x86_64_regs.rip;
954 /*i386_regs.xcs = x86_64_regs.cs;*/
955 /*i386_regs.eflags = x86_64_regs.eflags;*/
956 i386_regs.esp = x86_64_regs.rsp;
957 /*i386_regs.xss = x86_64_regs.ss;*/
958 }
959 }
Denys Vlasenko401374e2013-02-06 18:24:39 +0100960# elif defined(ARM)
961 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (void *)&arm_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100962# elif defined(AARCH64)
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100963 /*aarch64_io.iov_base = &arm_regs_union; - already is */
964 aarch64_io.iov_len = sizeof(arm_regs_union);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100965 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void *)&aarch64_io);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100966# if 0
967 /* Paranoia checks */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100968 if (get_regs_error)
969 return;
970 switch (aarch64_io.iov_len) {
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100971 case sizeof(aarch64_regs):
972 /* We are in 64-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100973 break;
974 case sizeof(arm_regs):
975 /* We are in 32-bit mode */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100976 break;
977 default:
978 get_regs_error = -1;
979 break;
980 }
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100981# endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100982# elif defined(SPARC) || defined(SPARC64)
983 get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&regs, 0);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100984# elif defined(TILE)
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500985 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &tile_regs);
Christian Svensson492f81f2013-02-14 13:26:27 +0100986# elif defined(OR1K)
987 or1k_io.iov_len = sizeof(or1k_regs);
988 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &or1k_io);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100989# endif
990}
991#endif
992
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200993/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100994 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
995 * 1: ok, continue in trace_syscall_entering().
996 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200997 * ("????" etc) and bail out.
998 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100999static int
Denys Vlasenko06602d92011-08-24 17:53:52 +02001000get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001001{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001002 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001003
Denys Vlasenko523635f2012-02-25 02:44:25 +01001004#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001005 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001006 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +00001007
1008 if (syscall_mode != -ENOSYS) {
1009 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001010 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +00001011 */
1012 scno = syscall_mode;
1013 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001014 /*
Michal Ludvig882eda82002-11-11 12:50:47 +00001015 * Old style of "passing" the scno via the SVC instruction.
1016 */
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001017 long psw;
Michal Ludvig882eda82002-11-11 12:50:47 +00001018 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001019 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +02001020 static const int gpr_offset[16] = {
1021 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
1022 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
1023 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
1024 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
1025 };
Roland McGrath761b5d72002-12-15 23:58:31 +00001026
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001027 if (upeek(tcp, PT_PSWADDR, &psw) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +00001028 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +00001029 errno = 0;
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001030 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(psw - sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +00001031 if (errno) {
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001032 perror_msg("%s", "peektext(psw-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +00001033 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +00001034 }
Michal Ludvig882eda82002-11-11 12:50:47 +00001035
1036 /*
1037 * We have to check if the SVC got executed directly or via an
1038 * EXECUTE instruction. In case of EXECUTE it is necessary to do
1039 * instruction decoding to derive the system call number.
1040 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
1041 * so that this doesn't work if a SVC opcode is part of an EXECUTE
1042 * opcode. Since there is no way to find out the opcode size this
1043 * is the best we can do...
1044 */
Michal Ludvig882eda82002-11-11 12:50:47 +00001045 if ((opcode & 0xff00) == 0x0a00) {
1046 /* SVC opcode */
1047 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +00001048 }
Michal Ludvig882eda82002-11-11 12:50:47 +00001049 else {
1050 /* SVC got executed by EXECUTE instruction */
1051
1052 /*
1053 * Do instruction decoding of EXECUTE. If you really want to
1054 * understand this, read the Principles of Operations.
1055 */
1056 svc_addr = (void *) (opcode & 0xfff);
1057
1058 tmp = 0;
1059 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001060 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001061 return -1;
1062 svc_addr += tmp;
1063
1064 tmp = 0;
1065 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001066 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001067 return -1;
1068 svc_addr += tmp;
1069
Denys Vlasenkofb036672009-01-23 16:30:26 +00001070 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +00001071 if (errno)
1072 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001073# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +00001074 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001075# else
Michal Ludvig882eda82002-11-11 12:50:47 +00001076 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001077# endif
Michal Ludvig882eda82002-11-11 12:50:47 +00001078 tmp = 0;
1079 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001080 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001081 return -1;
1082
1083 scno = (scno | tmp) & 0xff;
1084 }
1085 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001086#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001087 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001088 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001089# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001090 /* TODO: speed up strace by not doing this at every syscall.
1091 * We only need to do it after execve.
1092 */
1093 int currpers;
1094 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +02001095
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001096 /* Check for 64/32 bit mode. */
1097 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
1098 return -1;
1099 /* SF is bit 0 of MSR */
1100 if (val < 0)
1101 currpers = 0;
1102 else
1103 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001104 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001105# endif
1106#elif defined(AVR32)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001107 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001108#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001109 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001110 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001111#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001112 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +02001113#elif defined(X86_64) || defined(X32)
1114# ifndef __X32_SYSCALL_BIT
1115# define __X32_SYSCALL_BIT 0x40000000
1116# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001117 int currpers;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001118# if 1
1119 /* GETREGSET of NT_PRSTATUS tells us regset size,
1120 * which unambiguously detects i386.
1121 *
1122 * Linux kernel distinguishes x86-64 and x32 processes
1123 * solely by looking at __X32_SYSCALL_BIT:
1124 * arch/x86/include/asm/compat.h::is_x32_task():
1125 * if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)
1126 * return true;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001127 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001128 if (x86_io.iov_len == sizeof(i386_regs)) {
1129 scno = i386_regs.orig_eax;
1130 currpers = 1;
1131 } else {
1132 scno = x86_64_regs.orig_rax;
1133 currpers = 0;
1134 if (scno & __X32_SYSCALL_BIT) {
1135 scno -= __X32_SYSCALL_BIT;
1136 currpers = 2;
1137 }
1138 }
1139# elif 0
1140 /* cs = 0x33 for long mode (native 64 bit and x32)
1141 * cs = 0x23 for compatibility mode (32 bit)
1142 * ds = 0x2b for x32 mode (x86-64 in 32 bit)
1143 */
1144 scno = x86_64_regs.orig_rax;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001145 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001146 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +02001147 case 0x33:
1148 if (x86_64_regs.ds == 0x2b) {
1149 currpers = 2;
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001150 scno &= ~__X32_SYSCALL_BIT;
H.J. Lu35be5812012-04-16 13:00:01 +02001151 } else
1152 currpers = 0;
1153 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001154 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001155 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001156 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001157 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001158 currpers = current_personality;
1159 break;
1160 }
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001161# elif 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001162 /* This version analyzes the opcode of a syscall instruction.
1163 * (int 0x80 on i386 vs. syscall on x86-64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001164 * It works, but is too complicated, and strictly speaking, unreliable.
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001165 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001166 unsigned long call, rip = x86_64_regs.rip;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001167 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
1168 rip -= 2;
1169 errno = 0;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001170 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001171 if (errno)
1172 fprintf(stderr, "ptrace_peektext failed: %s\n",
1173 strerror(errno));
1174 switch (call & 0xffff) {
1175 /* x86-64: syscall = 0x0f 0x05 */
1176 case 0x050f: currpers = 0; break;
1177 /* i386: int 0x80 = 0xcd 0x80 */
1178 case 0x80cd: currpers = 1; break;
1179 default:
1180 currpers = current_personality;
1181 fprintf(stderr,
1182 "Unknown syscall opcode (0x%04X) while "
1183 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001184 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001185 break;
1186 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001187# endif
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001188
H.J. Lu35be5812012-04-16 13:00:01 +02001189# ifdef X32
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001190 /* If we are built for a x32 system, then personality 0 is x32
1191 * (not x86_64), and stracing of x86_64 apps is not supported.
1192 * Stracing of i386 apps is still supported.
H.J. Lu085e4282012-04-17 11:05:04 -07001193 */
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001194 if (currpers == 0) {
1195 fprintf(stderr, "syscall_%lu(...) in unsupported "
1196 "64-bit mode of process PID=%d\n",
1197 scno, tcp->pid);
1198 return 0;
H.J. Lu35be5812012-04-16 13:00:01 +02001199 }
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001200 currpers &= ~2; /* map 2,1 to 0,1 */
H.J. Lu35be5812012-04-16 13:00:01 +02001201# endif
H.J. Lu085e4282012-04-17 11:05:04 -07001202 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001203#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001204# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001205 long psr;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001206 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001207 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001208 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001209 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001210 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001211 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001212 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001213 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001214 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001215#elif defined(AARCH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001216 switch (aarch64_io.iov_len) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001217 case sizeof(aarch64_regs):
1218 /* We are in 64-bit mode */
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001219 scno = aarch64_regs.regs[8];
1220 update_personality(tcp, 1);
1221 break;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001222 case sizeof(arm_regs):
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001223 /* We are in 32-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001224 scno = arm_regs.ARM_r7;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001225 update_personality(tcp, 0);
1226 break;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001227 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001228#elif defined(ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001229 /*
1230 * We only need to grab the syscall number on syscall entry.
1231 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001232 if (arm_regs.ARM_ip == 0) {
Roland McGrath0f87c492003-06-03 23:29:04 +00001233 /*
Denys Vlasenko401374e2013-02-06 18:24:39 +01001234 * Note: we only deal with 32-bit CPUs here
Roland McGrath0f87c492003-06-03 23:29:04 +00001235 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001236 if (arm_regs.ARM_cpsr & 0x20) {
Roland McGrath0f87c492003-06-03 23:29:04 +00001237 /*
1238 * Get the Thumb-mode system call number
1239 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001240 scno = arm_regs.ARM_r7;
Roland McGrath0f87c492003-06-03 23:29:04 +00001241 } else {
1242 /*
1243 * Get the ARM-mode system call number
1244 */
1245 errno = 0;
Denys Vlasenko401374e2013-02-06 18:24:39 +01001246 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(arm_regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +00001247 if (errno)
1248 return -1;
1249
Roland McGrathf691bd22006-04-25 07:34:41 +00001250 /* Handle the EABI syscall convention. We do not
1251 bother converting structures between the two
1252 ABIs, but basic functionality should work even
1253 if strace and the traced program have different
1254 ABIs. */
1255 if (scno == 0xef000000) {
Denys Vlasenko401374e2013-02-06 18:24:39 +01001256 scno = arm_regs.ARM_r7;
Roland McGrathf691bd22006-04-25 07:34:41 +00001257 } else {
1258 if ((scno & 0x0ff00000) != 0x0f900000) {
1259 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1260 scno);
1261 return -1;
1262 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001263
Roland McGrathf691bd22006-04-25 07:34:41 +00001264 /*
1265 * Fixup the syscall number
1266 */
1267 scno &= 0x000fffff;
1268 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001269 }
Roland McGrath56703312008-05-20 01:35:55 +00001270 if (scno & 0x0f0000) {
1271 /*
1272 * Handle ARM specific syscall
1273 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001274 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +00001275 scno &= 0x0000ffff;
1276 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001277 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001278
Roland McGrath0f87c492003-06-03 23:29:04 +00001279 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001280 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1281 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001282 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001283#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001284 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001285 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001286#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001287 unsigned long long regs[38];
1288
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001289 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001290 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001291 mips_a3 = regs[REG_A3];
1292 mips_r2 = regs[REG_V0];
Roland McGrath542c2c62008-05-20 01:11:56 +00001293
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001294 scno = mips_r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001295 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001296 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001297 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001298 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001299 return 0;
1300 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001301 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001302#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001303 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001304 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001305 if (upeek(tcp, REG_V0, &scno) < 0)
1306 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001307
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001308 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001309 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001310 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001311 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001312 return 0;
1313 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001314 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001315#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001316 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001317 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001318 if (upeek(tcp, REG_R0, &scno) < 0)
1319 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001320
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001321 /*
1322 * Do some sanity checks to figure out if it's
1323 * really a syscall entry
1324 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001325 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001326 if (alpha_a3 == 0 || alpha_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001327 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001328 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001329 return 0;
1330 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001331 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001332#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001333 /* Disassemble the syscall trap. */
1334 /* Retrieve the syscall trap instruction. */
Denys Vlasenko46455822013-02-05 17:02:59 +01001335 unsigned long trap;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001336 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001337# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001338 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1339 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001340# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001341 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001342# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001343 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001344 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001345
1346 /* Disassemble the trap to see what personality to use. */
1347 switch (trap) {
1348 case 0x91d02010:
1349 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001350 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001351 break;
1352 case 0x91d0206d:
1353 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001354 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001355 break;
1356 case 0x91d02000:
1357 /* SunOS syscall trap. (pers 1) */
1358 fprintf(stderr, "syscall: SunOS no support\n");
1359 return -1;
1360 case 0x91d02008:
1361 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001362 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001363 break;
1364 case 0x91d02009:
1365 /* NetBSD/FreeBSD syscall trap. */
1366 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1367 return -1;
1368 case 0x91d02027:
1369 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001370 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001371 break;
1372 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001373# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001374 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001375# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001376 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001377# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001378 return -1;
1379 }
1380
1381 /* Extract the system call number from the registers. */
1382 if (trap == 0x91d02027)
1383 scno = 156;
1384 else
1385 scno = regs.u_regs[U_REG_G1];
1386 if (scno == 0) {
1387 scno = regs.u_regs[U_REG_O0];
1388 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1389 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001390#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001391 if (upeek(tcp, PT_GR20, &scno) < 0)
1392 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001393#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001394 /*
1395 * In the new syscall ABI, the system call number is in R3.
1396 */
1397 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1398 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001399
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001400 if (scno < 0) {
1401 /* Odd as it may seem, a glibc bug has been known to cause
1402 glibc to issue bogus negative syscall numbers. So for
1403 our purposes, make strace print what it *should* have been */
1404 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001405 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001406 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001407 "Detected glibc bug: bogus system call"
1408 " number = %ld, correcting to %ld\n",
1409 scno,
1410 correct_scno);
1411 scno = correct_scno;
1412 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001413#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001414 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001415 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001416 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001417#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001418 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1419 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001420#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001421 int currpers;
1422 scno = tile_regs.regs[10];
1423# ifdef __tilepro__
1424 currpers = 1;
1425# else
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001426# ifndef PT_FLAGS_COMPAT
1427# define PT_FLAGS_COMPAT 0x10000 /* from Linux 3.8 on */
1428# endif
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001429 if (tile_regs.flags & PT_FLAGS_COMPAT)
1430 currpers = 1;
1431 else
1432 currpers = 0;
1433# endif
1434 update_personality(tcp, currpers);
1435
1436 if (!(tcp->flags & TCB_INSYSCALL)) {
1437 /* Check if we return from execve. */
1438 if (tcp->flags & TCB_WAITEXECVE) {
1439 tcp->flags &= ~TCB_WAITEXECVE;
1440 return 0;
1441 }
1442 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001443#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001444 if (upeek(tcp, 0, &scno) < 0)
1445 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01001446#elif defined(OR1K)
1447 scno = or1k_regs.gpr[11];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001448#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001449
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001450 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001451 return 1;
1452}
1453
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001454/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001455 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001456 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1457 * 1: ok, continue in trace_syscall_entering().
1458 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001459 * ("????" etc) and bail out.
1460 */
Roland McGratha4d48532005-06-08 20:45:28 +00001461static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001462syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001463{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001464 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001465#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001466 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001467 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001468 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1469 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001470 }
H.J. Lu35be5812012-04-16 13:00:01 +02001471#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001472 {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001473 long rax;
1474 if (x86_io.iov_len == sizeof(i386_regs)) {
1475 /* Sign extend from 32 bits */
1476 rax = (int32_t)i386_regs.eax;
1477 } else {
1478 /* Note: in X32 build, this truncates 64 to 32 bits */
1479 rax = x86_64_regs.rax;
1480 }
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001481 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001482 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001483 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1484 return 0;
1485 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001486 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001487#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001488 /* TODO: we already fetched PT_GPR2 in get_scno
1489 * and stored it in syscall_mode, reuse it here
1490 * instead of re-fetching?
1491 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001492 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001493 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001494 if (syscall_mode != -ENOSYS)
1495 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001496 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001497 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001498 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001499 return 0;
1500 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001501#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001502 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001503 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001504 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001505 if (m68k_d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001506 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001507 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", m68k_d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001508 return 0;
1509 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001510#elif defined(IA64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001511 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001512 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001513 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001514 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001515 if (ia32 && ia64_r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001516 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001517 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", ia64_r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001518 return 0;
1519 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001520#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001521 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001522 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001523 if (cris_r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001524 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001525 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", cris_r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001526 return 0;
1527 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001528#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001529 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001530 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001531 if (microblaze_r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001532 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001533 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", microblaze_r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001534 return 0;
1535 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001536#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001537 return 1;
1538}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001539
Denys Vlasenko146b9442012-03-18 22:10:48 +01001540static void
1541internal_fork(struct tcb *tcp)
1542{
1543#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1544# define ARG_FLAGS 1
1545#else
1546# define ARG_FLAGS 0
1547#endif
1548#ifndef CLONE_UNTRACED
1549# define CLONE_UNTRACED 0x00800000
1550#endif
1551 if ((ptrace_setoptions
1552 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1553 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1554 return;
1555
1556 if (!followfork)
1557 return;
1558
1559 if (entering(tcp)) {
1560 /*
1561 * We won't see the new child if clone is called with
1562 * CLONE_UNTRACED, so we keep the same logic with that option
1563 * and don't trace it.
1564 */
1565 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1566 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1567 return;
1568 setbpt(tcp);
1569 } else {
1570 if (tcp->flags & TCB_BPTSET)
1571 clearbpt(tcp);
1572 }
1573}
1574
1575#if defined(TCB_WAITEXECVE)
1576static void
1577internal_exec(struct tcb *tcp)
1578{
1579 /* Maybe we have post-execve SIGTRAP suppressed? */
1580 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1581 return; /* yes, no need to do anything */
1582
1583 if (exiting(tcp) && syserror(tcp))
1584 /* Error in execve, no post-execve SIGTRAP expected */
1585 tcp->flags &= ~TCB_WAITEXECVE;
1586 else
1587 tcp->flags |= TCB_WAITEXECVE;
1588}
1589#endif
1590
1591static void
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001592syscall_fixup_for_fork_exec(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001593{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001594 /*
1595 * We must always trace a few critical system calls in order to
1596 * correctly support following forks in the presence of tracing
1597 * qualifiers.
1598 */
1599 int (*func)();
1600
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001601 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001602 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001603
1604 func = sysent[tcp->scno].sys_func;
1605
1606 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001607 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001608 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001609 ) {
1610 internal_fork(tcp);
1611 return;
1612 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001613
Denys Vlasenko84703742012-02-25 02:38:52 +01001614#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001615 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001616# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001617 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001618# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001619 ) {
1620 internal_exec(tcp);
1621 return;
1622 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001623#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001624}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001625
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001626/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001627static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001628get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001629{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001630 int i, nargs;
1631
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001632 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001633 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001634 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001635 nargs = tcp->u_nargs = MAX_ARGS;
1636
Denys Vlasenko523635f2012-02-25 02:44:25 +01001637#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001638 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001639 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1640 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001641#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001642 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001643 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1644 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001645#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001646 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001647 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001648 long rbs_end;
1649 /* be backwards compatible with kernel < 2.4.4... */
1650# ifndef PT_RBS_END
1651# define PT_RBS_END PT_AR_BSP
1652# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001653
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001654 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1655 return -1;
1656 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001657 return -1;
1658
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001659 sof = (cfm >> 0) & 0x7f;
1660 sol = (cfm >> 7) & 0x7f;
1661 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1662
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001663 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001664 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1665 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1666 return -1;
1667 }
1668 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001669 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1670 PT_R9 /* ECX = out1 */,
1671 PT_R10 /* EDX = out2 */,
1672 PT_R14 /* ESI = out3 */,
1673 PT_R15 /* EDI = out4 */,
1674 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001675
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001676 for (i = 0; i < nargs; ++i) {
1677 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1678 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001679 /* truncate away IVE sign-extension */
1680 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001681 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001682 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001683#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001684 /* N32 and N64 both use up to six registers. */
1685 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001686
1687 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1688 return -1;
1689
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001690 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001691 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001692# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001693 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001694# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001695 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001696#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001697 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001698 long sp;
1699
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001700 if (upeek(tcp, REG_SP, &sp) < 0)
1701 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001702 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001703 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1704 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001705 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001706 (char *)(tcp->u_arg + 4));
1707 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001708 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001709 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001710 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001711 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001712#elif defined(POWERPC)
1713# ifndef PT_ORIG_R3
1714# define PT_ORIG_R3 34
1715# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001716 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001717 if (upeek(tcp, (i==0) ?
1718 (sizeof(unsigned long) * PT_ORIG_R3) :
1719 ((i+PT_R3) * sizeof(unsigned long)),
1720 &tcp->u_arg[i]) < 0)
1721 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001722 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001723#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001724 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001725 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001726#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001727 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001728 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1729 return -1;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001730#elif defined(ARM) || defined(AARCH64)
1731# if defined(AARCH64)
1732 if (tcp->currpers == 1)
1733 for (i = 0; i < nargs; ++i)
1734 tcp->u_arg[i] = aarch64_regs.regs[i];
1735 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001736# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001737 for (i = 0; i < nargs; ++i)
Denys Vlasenko401374e2013-02-06 18:24:39 +01001738 tcp->u_arg[i] = arm_regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001739#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001740 (void)i;
1741 (void)nargs;
1742 tcp->u_arg[0] = regs.r12;
1743 tcp->u_arg[1] = regs.r11;
1744 tcp->u_arg[2] = regs.r10;
1745 tcp->u_arg[3] = regs.r9;
1746 tcp->u_arg[4] = regs.r5;
1747 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001748#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001749 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 +02001750
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001751 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001752 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1753 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001754#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001755 static const int syscall_regs[MAX_ARGS] = {
1756 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1757 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001758 };
1759
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001760 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001761 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001762 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001763#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001764 int i;
1765 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001766 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001767
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001768 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001769 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1770 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001771#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001772 (void)i;
1773 (void)nargs;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001774 if (x86_io.iov_len != sizeof(i386_regs)) {
1775 /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001776 tcp->u_arg[0] = x86_64_regs.rdi;
1777 tcp->u_arg[1] = x86_64_regs.rsi;
1778 tcp->u_arg[2] = x86_64_regs.rdx;
1779 tcp->u_arg[3] = x86_64_regs.r10;
1780 tcp->u_arg[4] = x86_64_regs.r8;
1781 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001782# ifdef X32
1783 tcp->ext_arg[0] = x86_64_regs.rdi;
1784 tcp->ext_arg[1] = x86_64_regs.rsi;
1785 tcp->ext_arg[2] = x86_64_regs.rdx;
1786 tcp->ext_arg[3] = x86_64_regs.r10;
1787 tcp->ext_arg[4] = x86_64_regs.r8;
1788 tcp->ext_arg[5] = x86_64_regs.r9;
1789# endif
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001790 } else {
1791 /* i386 ABI */
1792 /* Sign-extend from 32 bits */
1793 tcp->u_arg[0] = (long)(int32_t)i386_regs.ebx;
1794 tcp->u_arg[1] = (long)(int32_t)i386_regs.ecx;
1795 tcp->u_arg[2] = (long)(int32_t)i386_regs.edx;
1796 tcp->u_arg[3] = (long)(int32_t)i386_regs.esi;
1797 tcp->u_arg[4] = (long)(int32_t)i386_regs.edi;
1798 tcp->u_arg[5] = (long)(int32_t)i386_regs.ebp;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001799 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001800#elif defined(MICROBLAZE)
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, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1803 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001804#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001805 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001806 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001807 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001808 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001809
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001810 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001811 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1812 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001813#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001814 for (i = 0; i < nargs; ++i)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001815 tcp->u_arg[i] = tile_regs.regs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001816#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001817 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001818 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1819 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001820#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001821 (void)i;
1822 (void)nargs;
1823 tcp->u_arg[0] = i386_regs.ebx;
1824 tcp->u_arg[1] = i386_regs.ecx;
1825 tcp->u_arg[2] = i386_regs.edx;
1826 tcp->u_arg[3] = i386_regs.esi;
1827 tcp->u_arg[4] = i386_regs.edi;
1828 tcp->u_arg[5] = i386_regs.ebp;
Christian Svensson492f81f2013-02-14 13:26:27 +01001829#elif defined(OR1K)
1830 (void)nargs;
1831 for (i = 0; i < 6; ++i)
1832 tcp->u_arg[i] = or1k_regs.gpr[3 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001833#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001834 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001835 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1836 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001837#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001838 return 1;
1839}
1840
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001841static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001842trace_syscall_entering(struct tcb *tcp)
1843{
1844 int res, scno_good;
1845
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001846#if defined TCB_WAITEXECVE
1847 if (tcp->flags & TCB_WAITEXECVE) {
1848 /* This is the post-execve SIGTRAP. */
1849 tcp->flags &= ~TCB_WAITEXECVE;
1850 return 0;
1851 }
1852#endif
1853
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001854 scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001855 if (res == 0)
1856 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001857 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001858 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001859 if (res == 0)
1860 return res;
1861 if (res == 1)
1862 res = get_syscall_args(tcp);
1863 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001864
1865 if (res != 1) {
1866 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001867 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001868 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001869 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001870 tprintf("syscall_%lu(", tcp->scno);
1871 else
1872 tprintf("%s(", sysent[tcp->scno].sys_name);
1873 /*
1874 * " <unavailable>" will be added later by the code which
1875 * detects ptrace errors.
1876 */
1877 goto ret;
1878 }
1879
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001880#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1881 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001882# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001883 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001884 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001885 break;
1886 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001887# endif
1888# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001889 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001890 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001891 break;
1892 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001893# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001894 break;
1895 }
1896#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1897
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001898 if (need_fork_exec_workarounds)
1899 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001900
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001901 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001902 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1903 (tracing_paths && !pathtrace_match(tcp))) {
1904 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1905 return 0;
1906 }
1907
1908 tcp->flags &= ~TCB_FILTERED;
1909
1910 if (cflag == CFLAG_ONLY_STATS) {
1911 res = 0;
1912 goto ret;
1913 }
1914
1915 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001916 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001917 tprintf("syscall_%lu(", tcp->scno);
1918 else
1919 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001920 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001921 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1922 sysent[tcp->scno].sys_func != sys_exit))
1923 res = printargs(tcp);
1924 else
1925 res = (*sysent[tcp->scno].sys_func)(tcp);
1926
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001927 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001928 ret:
1929 tcp->flags |= TCB_INSYSCALL;
1930 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001931 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001932 gettimeofday(&tcp->etime, NULL);
1933 return res;
1934}
1935
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001936/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001937 * 1: ok, continue in trace_syscall_exiting().
1938 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001939 * ("????" etc) and bail out.
1940 */
1941static int
1942get_syscall_result(struct tcb *tcp)
1943{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001944#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001945 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1946 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001947#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001948# define SO_MASK 0x10000000
1949 {
1950 long flags;
1951 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1952 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001953 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001954 return -1;
1955 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001956 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001957 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001958#elif defined(AVR32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001959 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001960#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001961 if (upeek(tcp, PT_R0, &bfin_r0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001962 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001963#elif defined(I386)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001964 /* already done by get_regs */
H.J. Lu35be5812012-04-16 13:00:01 +02001965#elif defined(X86_64) || defined(X32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001966 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001967#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001968# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001969 long psr;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001970 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1971 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001972 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001973 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001974 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001975 return -1;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001976#elif defined(ARM)
1977 /* already done by get_regs */
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001978#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001979 /* register reading already done by get_regs */
1980
1981 /* Used to do this, but we did it on syscall entry already: */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001982 /* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
1983 * else it's personality 0.
1984 */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001985 /*update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));*/
Denys Vlasenko523635f2012-02-25 02:44:25 +01001986#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001987 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001988 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001989#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001990 unsigned long long regs[38];
1991
1992 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1993 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001994 mips_a3 = regs[REG_A3];
1995 mips_r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001996#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001997 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001998 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001999 if (upeek(tcp, REG_V0, &mips_r2) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002000 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002001#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002002 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002003 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002004 if (upeek(tcp, REG_R0, &alpha_r0) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002005 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002006#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002007 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002008#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002009 if (upeek(tcp, PT_GR28, &hppa_r28) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002010 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002011#elif defined(SH)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002012 /* new syscall ABI returns result in R0 */
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002013 if (upeek(tcp, 4*REG_REG0, (long *)&sh_r0) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002014 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002015#elif defined(SH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002016 /* ABI defines result returned in r9 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002017 if (upeek(tcp, REG_GENERAL(9), (long *)&sh64_r9) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002018 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002019#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002020 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002021 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002022#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002023 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002024#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002025 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002026 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01002027#elif defined(OR1K)
2028 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002029#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002030 return 1;
2031}
2032
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002033/* Called at each syscall exit */
2034static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002035syscall_fixup_on_sysexit(struct tcb *tcp)
2036{
Denys Vlasenko523635f2012-02-25 02:44:25 +01002037#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002038 if (syscall_mode != -ENOSYS)
2039 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02002040 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002041 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
2042 /*
2043 * Return from execve.
2044 * Fake a return value of zero. We leave the TCB_WAITEXECVE
2045 * flag set for the post-execve SIGTRAP to see and reset.
2046 */
2047 gpr2 = 0;
2048 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002049#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002050}
2051
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002052/*
2053 * Check the syscall return value register value for whether it is
2054 * a negated errno code indicating an error, or a success return value.
2055 */
2056static inline int
2057is_negated_errno(unsigned long int val)
2058{
2059 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002060#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01002061 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002062 val = (unsigned int) val;
2063 max = (unsigned int) max;
2064 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002065#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002066 return val > max;
2067}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002068
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002069#if defined(X32)
2070static inline int
2071is_negated_errno_x32(unsigned long long val)
2072{
2073 unsigned long long max = -(long long) nerrnos;
2074 /*
2075 * current_wordsize is 4 even in personality 0 (native X32)
2076 * but truncation _must not_ be done in it.
2077 * can't check current_wordsize here!
2078 */
2079 if (current_personality != 0) {
2080 val = (uint32_t) val;
2081 max = (uint32_t) max;
2082 }
2083 return val > max;
2084}
2085#endif
2086
Denys Vlasenko907735a2012-03-21 00:23:16 +01002087/* Returns:
2088 * 1: ok, continue in trace_syscall_exiting().
2089 * -1: error, trace_syscall_exiting() should print error indicator
2090 * ("????" etc) and bail out.
2091 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002092static int
2093get_error(struct tcb *tcp)
2094{
2095 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002096 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002097 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002098 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
2099 check_errno = 0;
2100 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002101#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002102 if (check_errno && is_negated_errno(gpr2)) {
2103 tcp->u_rval = -1;
2104 u_error = -gpr2;
2105 }
2106 else {
2107 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002108 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002109#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002110 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002111 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002112 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002113 }
2114 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002115 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002116 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002117#elif defined(X86_64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002118 long rax;
2119 if (x86_io.iov_len == sizeof(i386_regs)) {
2120 /* Sign extend from 32 bits */
2121 rax = (int32_t)i386_regs.eax;
2122 } else {
2123 rax = x86_64_regs.rax;
2124 }
2125 if (check_errno && is_negated_errno(rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002126 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002127 u_error = -rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002128 }
2129 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002130 tcp->u_rval = rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002131 }
2132#elif defined(X32)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002133 /* In X32, return value is 64-bit (llseek uses one).
2134 * Using merely "long rax" would not work.
2135 */
2136 long long rax;
2137 if (x86_io.iov_len == sizeof(i386_regs)) {
2138 /* Sign extend from 32 bits */
2139 rax = (int32_t)i386_regs.eax;
2140 } else {
2141 rax = x86_64_regs.rax;
2142 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002143 /* Careful: is_negated_errno() works only on longs */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002144 if (check_errno && is_negated_errno_x32(rax)) {
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002145 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002146 u_error = -rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002147 }
2148 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002149 tcp->u_rval = rax; /* truncating */
2150 tcp->u_lrval = rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002151 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002152#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002153 if (ia32) {
2154 int err;
2155
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002156 err = (int)ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002157 if (check_errno && is_negated_errno(err)) {
2158 tcp->u_rval = -1;
2159 u_error = -err;
2160 }
2161 else {
2162 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002163 }
2164 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002165 if (check_errno && ia64_r10) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002166 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002167 u_error = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002168 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002169 tcp->u_rval = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002170 }
2171 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002172#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002173 if (check_errno && mips_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002174 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002175 u_error = mips_r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002176 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002177 tcp->u_rval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002178# if defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002179 tcp->u_lrval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002180# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002181 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002182#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002183 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002184 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002185 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002186 }
2187 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002188 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002189 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002190#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002191 if (check_errno && is_negated_errno(m68k_d0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002192 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002193 u_error = -m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002194 }
2195 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002196 tcp->u_rval = m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002197 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002198#elif defined(ARM) || defined(AARCH64)
2199# if defined(AARCH64)
2200 if (tcp->currpers == 1) {
2201 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2202 tcp->u_rval = -1;
2203 u_error = -aarch64_regs.regs[0];
2204 }
2205 else {
2206 tcp->u_rval = aarch64_regs.regs[0];
2207 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002208 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002209 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01002210# endif
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002211 {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002212 if (check_errno && is_negated_errno(arm_regs.ARM_r0)) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002213 tcp->u_rval = -1;
Denys Vlasenko401374e2013-02-06 18:24:39 +01002214 u_error = -arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002215 }
2216 else {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002217 tcp->u_rval = arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002218 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002219 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002220#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002221 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
2222 tcp->u_rval = -1;
2223 u_error = -regs.r12;
2224 }
2225 else {
2226 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002227 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002228#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002229 if (check_errno && is_negated_errno(bfin_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002230 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002231 u_error = -bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002232 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002233 tcp->u_rval = bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002234 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002235#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002236 if (check_errno && alpha_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002237 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002238 u_error = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002239 }
2240 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002241 tcp->u_rval = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002242 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002243#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002244 if (check_errno && regs.psr & PSR_C) {
2245 tcp->u_rval = -1;
2246 u_error = regs.u_regs[U_REG_O0];
2247 }
2248 else {
2249 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002250 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002251#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002252 if (check_errno && regs.tstate & 0x1100000000UL) {
2253 tcp->u_rval = -1;
2254 u_error = regs.u_regs[U_REG_O0];
2255 }
2256 else {
2257 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002258 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002259#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002260 if (check_errno && is_negated_errno(hppa_r28)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002261 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002262 u_error = -hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002263 }
2264 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002265 tcp->u_rval = hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002266 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002267#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002268 if (check_errno && is_negated_errno(sh_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002269 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002270 u_error = -sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002271 }
2272 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002273 tcp->u_rval = sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002274 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002275#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002276 if (check_errno && is_negated_errno(sh64_r9)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002277 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002278 u_error = -sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002279 }
2280 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002281 tcp->u_rval = sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002282 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002283#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002284 if (check_errno && cris_r10 && (unsigned) -cris_r10 < nerrnos) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002285 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002286 u_error = -cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002287 }
2288 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002289 tcp->u_rval = cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002290 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002291#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002292 /*
2293 * The standard tile calling convention returns the value (or negative
2294 * errno) in r0, and zero (or positive errno) in r1.
2295 * Until at least kernel 3.8, however, the r1 value is not reflected
2296 * in ptregs at this point, so we use r0 here.
2297 */
2298 if (check_errno && is_negated_errno(tile_regs.regs[0])) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002299 tcp->u_rval = -1;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002300 u_error = -tile_regs.regs[0];
2301 } else {
2302 tcp->u_rval = tile_regs.regs[0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002303 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002304#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002305 if (check_errno && is_negated_errno(microblaze_r3)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002306 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002307 u_error = -microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002308 }
2309 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002310 tcp->u_rval = microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002311 }
Christian Svensson492f81f2013-02-14 13:26:27 +01002312#elif defined(OR1K)
2313 if (check_errno && is_negated_errno(or1k_regs.gpr[11])) {
2314 tcp->u_rval = -1;
2315 u_error = -or1k_regs.gpr[11];
2316 }
2317 else {
2318 tcp->u_rval = or1k_regs.gpr[11];
2319 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002320#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002321 tcp->u_error = u_error;
2322 return 1;
2323}
2324
2325static void
2326dumpio(struct tcb *tcp)
2327{
2328 if (syserror(tcp))
2329 return;
2330 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
2331 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002332 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002333 return;
2334 if (sysent[tcp->scno].sys_func == printargs)
2335 return;
2336 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
2337 if (sysent[tcp->scno].sys_func == sys_read ||
2338 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002339 sysent[tcp->scno].sys_func == sys_recv ||
2340 sysent[tcp->scno].sys_func == sys_recvfrom)
2341 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
2342 else if (sysent[tcp->scno].sys_func == sys_readv)
2343 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2344 return;
2345 }
2346 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
2347 if (sysent[tcp->scno].sys_func == sys_write ||
2348 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002349 sysent[tcp->scno].sys_func == sys_send ||
2350 sysent[tcp->scno].sys_func == sys_sendto)
2351 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
2352 else if (sysent[tcp->scno].sys_func == sys_writev)
2353 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2354 return;
2355 }
2356}
2357
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002358static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002359trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002360{
2361 int sys_res;
2362 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002363 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002364 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002365
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002366 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002367 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002368 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002369
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002370#if SUPPORTED_PERSONALITIES > 1
2371 update_personality(tcp, tcp->currpers);
2372#endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002373 res = (get_regs_error ? -1 : get_syscall_result(tcp));
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002374 if (res == 1) {
2375 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01002376 res = get_error(tcp); /* returns 1 or -1 */
2377 if (res == 1) {
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01002378 if (need_fork_exec_workarounds)
2379 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01002380 if (filtered(tcp)) {
2381 goto ret;
2382 }
2383 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002384 }
2385
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002386 if (cflag) {
2387 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002388 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002389 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002390 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002391 }
2392 }
2393
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002394 /* If not in -ff mode, and printing_tcp != tcp,
2395 * then the log currently does not end with output
2396 * of _our syscall entry_, but with something else.
2397 * We need to say which syscall's return is this.
2398 *
2399 * Forced reprinting via TCB_REPRINT is used only by
2400 * "strace -ff -oLOG test/threaded_execve" corner case.
2401 * It's the only case when -ff mode needs reprinting.
2402 */
2403 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2404 tcp->flags &= ~TCB_REPRINT;
2405 printleader(tcp);
2406 if (!SCNO_IN_RANGE(tcp->scno))
2407 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2408 else
2409 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2410 }
2411 printing_tcp = tcp;
2412
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002413 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002414 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002415 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002416 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002417 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002418 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002419 tcp->flags &= ~TCB_INSYSCALL;
2420 return res;
2421 }
2422
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002423 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002424 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002425 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002426 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002427 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002428 /* FIXME: not_failing_only (IOW, option -z) is broken:
2429 * failure of syscall is known only after syscall return.
2430 * Thus we end up with something like this on, say, ENOENT:
2431 * open("doesnt_exist", O_RDONLY <unfinished ...>
2432 * {next syscall decode}
2433 * whereas the intended result is that open(...) line
2434 * is not shown at all.
2435 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002436 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002437 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002438 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2439 }
2440
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002441 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002442 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002443 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002444 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002445 qual_flags[tcp->scno] & QUAL_RAW) {
2446 if (u_error)
2447 tprintf("= -1 (errno %ld)", u_error);
2448 else
2449 tprintf("= %#lx", tcp->u_rval);
2450 }
2451 else if (!(sys_res & RVAL_NONE) && u_error) {
2452 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002453 /* Blocked signals do not interrupt any syscalls.
2454 * In this case syscalls don't return ERESTARTfoo codes.
2455 *
2456 * Deadly signals set to SIG_DFL interrupt syscalls
2457 * and kill the process regardless of which of the codes below
2458 * is returned by the interrupted syscall.
2459 * In some cases, kernel forces a kernel-generated deadly
2460 * signal to be unblocked and set to SIG_DFL (and thus cause
2461 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2462 * or SIGILL. (The alternative is to leave process spinning
2463 * forever on the faulty instruction - not useful).
2464 *
2465 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2466 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2467 * but kernel will always restart them.
2468 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002469 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002470 /* Most common type of signal-interrupted syscall exit code.
2471 * The system call will be restarted with the same arguments
2472 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2473 */
2474 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002475 break;
2476 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002477 /* Rare. For example, fork() returns this if interrupted.
2478 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2479 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002480 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002481 break;
2482 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002483 /* pause(), rt_sigsuspend() etc use this code.
2484 * SA_RESTART is ignored (assumed not set):
2485 * syscall won't restart (will return EINTR instead)
2486 * even after signal with SA_RESTART set.
2487 * However, after SIG_IGN or SIG_DFL signal it will.
2488 */
2489 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002490 break;
2491 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002492 /* Syscalls like nanosleep(), poll() which can't be
2493 * restarted with their original arguments use this
2494 * code. Kernel will execute restart_syscall() instead,
2495 * which changes arguments before restarting syscall.
2496 * SA_RESTART is ignored (assumed not set) similarly
2497 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2498 * since restart data is saved in "restart block"
2499 * in task struct, and if signal handler uses a syscall
2500 * which in turn saves another such restart block,
2501 * old data is lost and restart becomes impossible)
2502 */
2503 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002504 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002505 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002506 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002507 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002508 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002509 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002510 strerror(u_error));
2511 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002512 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002513 strerror(u_error));
2514 break;
2515 }
2516 if ((sys_res & RVAL_STR) && tcp->auxstr)
2517 tprintf(" (%s)", tcp->auxstr);
2518 }
2519 else {
2520 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002521 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002522 else {
2523 switch (sys_res & RVAL_MASK) {
2524 case RVAL_HEX:
2525 tprintf("= %#lx", tcp->u_rval);
2526 break;
2527 case RVAL_OCTAL:
2528 tprintf("= %#lo", tcp->u_rval);
2529 break;
2530 case RVAL_UDECIMAL:
2531 tprintf("= %lu", tcp->u_rval);
2532 break;
2533 case RVAL_DECIMAL:
2534 tprintf("= %ld", tcp->u_rval);
2535 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002536#if defined(LINUX_MIPSN32) || defined(X32)
2537 /*
2538 case RVAL_LHEX:
2539 tprintf("= %#llx", tcp->u_lrval);
2540 break;
2541 case RVAL_LOCTAL:
2542 tprintf("= %#llo", tcp->u_lrval);
2543 break;
2544 */
2545 case RVAL_LUDECIMAL:
2546 tprintf("= %llu", tcp->u_lrval);
2547 break;
2548 /*
2549 case RVAL_LDECIMAL:
2550 tprintf("= %lld", tcp->u_lrval);
2551 break;
2552 */
2553#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002554 default:
2555 fprintf(stderr,
2556 "invalid rval format\n");
2557 break;
2558 }
2559 }
2560 if ((sys_res & RVAL_STR) && tcp->auxstr)
2561 tprintf(" (%s)", tcp->auxstr);
2562 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002563 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002564 tv_sub(&tv, &tv, &tcp->etime);
2565 tprintf(" <%ld.%06ld>",
2566 (long) tv.tv_sec, (long) tv.tv_usec);
2567 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002568 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002569 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002570 line_ended();
2571
Denys Vlasenko3b738812011-08-22 02:06:35 +02002572 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002573 tcp->flags &= ~TCB_INSYSCALL;
2574 return 0;
2575}
2576
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002577int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002578trace_syscall(struct tcb *tcp)
2579{
2580 return exiting(tcp) ?
2581 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2582}