blob: 448f37d631fe8b120172e1752167f9431fe3816a [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;
Denys Vlasenko6cf36052013-02-15 15:01:38 +01001771#elif defined(I386)
1772 (void)i;
1773 (void)nargs;
1774 tcp->u_arg[0] = i386_regs.ebx;
1775 tcp->u_arg[1] = i386_regs.ecx;
1776 tcp->u_arg[2] = i386_regs.edx;
1777 tcp->u_arg[3] = i386_regs.esi;
1778 tcp->u_arg[4] = i386_regs.edi;
1779 tcp->u_arg[5] = i386_regs.ebp;
H.J. Lu35be5812012-04-16 13:00:01 +02001780#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001781 (void)i;
1782 (void)nargs;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001783 if (x86_io.iov_len != sizeof(i386_regs)) {
1784 /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001785 tcp->u_arg[0] = x86_64_regs.rdi;
1786 tcp->u_arg[1] = x86_64_regs.rsi;
1787 tcp->u_arg[2] = x86_64_regs.rdx;
1788 tcp->u_arg[3] = x86_64_regs.r10;
1789 tcp->u_arg[4] = x86_64_regs.r8;
1790 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001791# ifdef X32
1792 tcp->ext_arg[0] = x86_64_regs.rdi;
1793 tcp->ext_arg[1] = x86_64_regs.rsi;
1794 tcp->ext_arg[2] = x86_64_regs.rdx;
1795 tcp->ext_arg[3] = x86_64_regs.r10;
1796 tcp->ext_arg[4] = x86_64_regs.r8;
1797 tcp->ext_arg[5] = x86_64_regs.r9;
1798# endif
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001799 } else {
1800 /* i386 ABI */
Denys Vlasenko6cf36052013-02-15 15:01:38 +01001801 /* Zero-extend from 32 bits */
1802 /* Use widen_to_long(tcp->u_arg[N]) in syscall handlers
1803 * if you need to use *sign-extended* parameter.
1804 */
1805 tcp->u_arg[0] = (long)(uint32_t)i386_regs.ebx;
1806 tcp->u_arg[1] = (long)(uint32_t)i386_regs.ecx;
1807 tcp->u_arg[2] = (long)(uint32_t)i386_regs.edx;
1808 tcp->u_arg[3] = (long)(uint32_t)i386_regs.esi;
1809 tcp->u_arg[4] = (long)(uint32_t)i386_regs.edi;
1810 tcp->u_arg[5] = (long)(uint32_t)i386_regs.ebp;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001811 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001812#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001813 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001814 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1815 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001816#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001817 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001818 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001819 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001820 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001821
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001822 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001823 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1824 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001825#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001826 for (i = 0; i < nargs; ++i)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001827 tcp->u_arg[i] = tile_regs.regs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001828#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001829 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001830 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1831 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01001832#elif defined(OR1K)
1833 (void)nargs;
1834 for (i = 0; i < 6; ++i)
1835 tcp->u_arg[i] = or1k_regs.gpr[3 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001836#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001837 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001838 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1839 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001840#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001841 return 1;
1842}
1843
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001844static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001845trace_syscall_entering(struct tcb *tcp)
1846{
1847 int res, scno_good;
1848
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001849#if defined TCB_WAITEXECVE
1850 if (tcp->flags & TCB_WAITEXECVE) {
1851 /* This is the post-execve SIGTRAP. */
1852 tcp->flags &= ~TCB_WAITEXECVE;
1853 return 0;
1854 }
1855#endif
1856
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001857 scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001858 if (res == 0)
1859 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001860 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001861 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001862 if (res == 0)
1863 return res;
1864 if (res == 1)
1865 res = get_syscall_args(tcp);
1866 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001867
1868 if (res != 1) {
1869 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001870 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001871 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001872 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001873 tprintf("syscall_%lu(", tcp->scno);
1874 else
1875 tprintf("%s(", sysent[tcp->scno].sys_name);
1876 /*
1877 * " <unavailable>" will be added later by the code which
1878 * detects ptrace errors.
1879 */
1880 goto ret;
1881 }
1882
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001883#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1884 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001885# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001886 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001887 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001888 break;
1889 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001890# endif
1891# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001892 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001893 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001894 break;
1895 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001896# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001897 break;
1898 }
1899#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1900
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001901 if (need_fork_exec_workarounds)
1902 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001903
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001904 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001905 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1906 (tracing_paths && !pathtrace_match(tcp))) {
1907 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1908 return 0;
1909 }
1910
1911 tcp->flags &= ~TCB_FILTERED;
1912
1913 if (cflag == CFLAG_ONLY_STATS) {
1914 res = 0;
1915 goto ret;
1916 }
1917
1918 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001919 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001920 tprintf("syscall_%lu(", tcp->scno);
1921 else
1922 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001923 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001924 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1925 sysent[tcp->scno].sys_func != sys_exit))
1926 res = printargs(tcp);
1927 else
1928 res = (*sysent[tcp->scno].sys_func)(tcp);
1929
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001930 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001931 ret:
1932 tcp->flags |= TCB_INSYSCALL;
1933 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001934 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001935 gettimeofday(&tcp->etime, NULL);
1936 return res;
1937}
1938
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001939/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001940 * 1: ok, continue in trace_syscall_exiting().
1941 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001942 * ("????" etc) and bail out.
1943 */
1944static int
1945get_syscall_result(struct tcb *tcp)
1946{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001947#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001948 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1949 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001950#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001951# define SO_MASK 0x10000000
1952 {
1953 long flags;
1954 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1955 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001956 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001957 return -1;
1958 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001959 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001960 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001961#elif defined(AVR32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001962 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001963#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001964 if (upeek(tcp, PT_R0, &bfin_r0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001965 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001966#elif defined(I386)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001967 /* already done by get_regs */
H.J. Lu35be5812012-04-16 13:00:01 +02001968#elif defined(X86_64) || defined(X32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001969 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001970#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001971# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001972 long psr;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001973 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1974 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001975 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001976 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001977 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001978 return -1;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001979#elif defined(ARM)
1980 /* already done by get_regs */
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001981#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001982 /* register reading already done by get_regs */
1983
1984 /* Used to do this, but we did it on syscall entry already: */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001985 /* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
1986 * else it's personality 0.
1987 */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001988 /*update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));*/
Denys Vlasenko523635f2012-02-25 02:44:25 +01001989#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001990 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001991 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001992#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001993 unsigned long long regs[38];
1994
1995 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1996 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001997 mips_a3 = regs[REG_A3];
1998 mips_r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001999#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002000 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002001 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002002 if (upeek(tcp, REG_V0, &mips_r2) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002003 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002004#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002005 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002006 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002007 if (upeek(tcp, REG_R0, &alpha_r0) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002008 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002009#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002010 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002011#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002012 if (upeek(tcp, PT_GR28, &hppa_r28) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002013 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002014#elif defined(SH)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002015 /* new syscall ABI returns result in R0 */
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002016 if (upeek(tcp, 4*REG_REG0, (long *)&sh_r0) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002017 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002018#elif defined(SH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002019 /* ABI defines result returned in r9 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002020 if (upeek(tcp, REG_GENERAL(9), (long *)&sh64_r9) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002021 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002022#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002023 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002024 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002025#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002026 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002027#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002028 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002029 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01002030#elif defined(OR1K)
2031 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002032#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002033 return 1;
2034}
2035
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002036/* Called at each syscall exit */
2037static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002038syscall_fixup_on_sysexit(struct tcb *tcp)
2039{
Denys Vlasenko523635f2012-02-25 02:44:25 +01002040#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002041 if (syscall_mode != -ENOSYS)
2042 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02002043 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002044 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
2045 /*
2046 * Return from execve.
2047 * Fake a return value of zero. We leave the TCB_WAITEXECVE
2048 * flag set for the post-execve SIGTRAP to see and reset.
2049 */
2050 gpr2 = 0;
2051 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002052#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002053}
2054
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002055/*
2056 * Check the syscall return value register value for whether it is
2057 * a negated errno code indicating an error, or a success return value.
2058 */
2059static inline int
2060is_negated_errno(unsigned long int val)
2061{
2062 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002063#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01002064 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002065 val = (unsigned int) val;
2066 max = (unsigned int) max;
2067 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002068#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002069 return val > max;
2070}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002071
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002072#if defined(X32)
2073static inline int
2074is_negated_errno_x32(unsigned long long val)
2075{
2076 unsigned long long max = -(long long) nerrnos;
2077 /*
2078 * current_wordsize is 4 even in personality 0 (native X32)
2079 * but truncation _must not_ be done in it.
2080 * can't check current_wordsize here!
2081 */
2082 if (current_personality != 0) {
2083 val = (uint32_t) val;
2084 max = (uint32_t) max;
2085 }
2086 return val > max;
2087}
2088#endif
2089
Denys Vlasenko907735a2012-03-21 00:23:16 +01002090/* Returns:
2091 * 1: ok, continue in trace_syscall_exiting().
2092 * -1: error, trace_syscall_exiting() should print error indicator
2093 * ("????" etc) and bail out.
2094 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002095static int
2096get_error(struct tcb *tcp)
2097{
2098 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002099 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002100 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002101 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
2102 check_errno = 0;
2103 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002104#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002105 if (check_errno && is_negated_errno(gpr2)) {
2106 tcp->u_rval = -1;
2107 u_error = -gpr2;
2108 }
2109 else {
2110 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002111 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002112#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002113 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002114 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002115 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002116 }
2117 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002118 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002119 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002120#elif defined(X86_64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002121 long rax;
2122 if (x86_io.iov_len == sizeof(i386_regs)) {
2123 /* Sign extend from 32 bits */
2124 rax = (int32_t)i386_regs.eax;
2125 } else {
2126 rax = x86_64_regs.rax;
2127 }
2128 if (check_errno && is_negated_errno(rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002129 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002130 u_error = -rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002131 }
2132 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002133 tcp->u_rval = rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002134 }
2135#elif defined(X32)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002136 /* In X32, return value is 64-bit (llseek uses one).
2137 * Using merely "long rax" would not work.
2138 */
2139 long long rax;
2140 if (x86_io.iov_len == sizeof(i386_regs)) {
2141 /* Sign extend from 32 bits */
2142 rax = (int32_t)i386_regs.eax;
2143 } else {
2144 rax = x86_64_regs.rax;
2145 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002146 /* Careful: is_negated_errno() works only on longs */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002147 if (check_errno && is_negated_errno_x32(rax)) {
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002148 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002149 u_error = -rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002150 }
2151 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002152 tcp->u_rval = rax; /* truncating */
2153 tcp->u_lrval = rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002154 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002155#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002156 if (ia32) {
2157 int err;
2158
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002159 err = (int)ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002160 if (check_errno && is_negated_errno(err)) {
2161 tcp->u_rval = -1;
2162 u_error = -err;
2163 }
2164 else {
2165 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002166 }
2167 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002168 if (check_errno && ia64_r10) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002169 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002170 u_error = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002171 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002172 tcp->u_rval = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002173 }
2174 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002175#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002176 if (check_errno && mips_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002177 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002178 u_error = mips_r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002179 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002180 tcp->u_rval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002181# if defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002182 tcp->u_lrval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002183# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002184 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002185#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002186 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002187 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002188 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002189 }
2190 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002191 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002192 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002193#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002194 if (check_errno && is_negated_errno(m68k_d0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002195 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002196 u_error = -m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002197 }
2198 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002199 tcp->u_rval = m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002200 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002201#elif defined(ARM) || defined(AARCH64)
2202# if defined(AARCH64)
2203 if (tcp->currpers == 1) {
2204 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2205 tcp->u_rval = -1;
2206 u_error = -aarch64_regs.regs[0];
2207 }
2208 else {
2209 tcp->u_rval = aarch64_regs.regs[0];
2210 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002211 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002212 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01002213# endif
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002214 {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002215 if (check_errno && is_negated_errno(arm_regs.ARM_r0)) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002216 tcp->u_rval = -1;
Denys Vlasenko401374e2013-02-06 18:24:39 +01002217 u_error = -arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002218 }
2219 else {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002220 tcp->u_rval = arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002221 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002222 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002223#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002224 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
2225 tcp->u_rval = -1;
2226 u_error = -regs.r12;
2227 }
2228 else {
2229 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002230 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002231#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002232 if (check_errno && is_negated_errno(bfin_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002233 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002234 u_error = -bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002235 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002236 tcp->u_rval = bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002237 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002238#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002239 if (check_errno && alpha_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002240 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002241 u_error = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002242 }
2243 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002244 tcp->u_rval = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002245 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002246#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002247 if (check_errno && regs.psr & PSR_C) {
2248 tcp->u_rval = -1;
2249 u_error = regs.u_regs[U_REG_O0];
2250 }
2251 else {
2252 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002253 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002254#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002255 if (check_errno && regs.tstate & 0x1100000000UL) {
2256 tcp->u_rval = -1;
2257 u_error = regs.u_regs[U_REG_O0];
2258 }
2259 else {
2260 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002261 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002262#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002263 if (check_errno && is_negated_errno(hppa_r28)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002264 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002265 u_error = -hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002266 }
2267 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002268 tcp->u_rval = hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002269 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002270#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002271 if (check_errno && is_negated_errno(sh_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002272 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002273 u_error = -sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002274 }
2275 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002276 tcp->u_rval = sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002277 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002278#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002279 if (check_errno && is_negated_errno(sh64_r9)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002280 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002281 u_error = -sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002282 }
2283 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002284 tcp->u_rval = sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002285 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002286#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002287 if (check_errno && cris_r10 && (unsigned) -cris_r10 < nerrnos) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002288 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002289 u_error = -cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002290 }
2291 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002292 tcp->u_rval = cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002293 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002294#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002295 /*
2296 * The standard tile calling convention returns the value (or negative
2297 * errno) in r0, and zero (or positive errno) in r1.
2298 * Until at least kernel 3.8, however, the r1 value is not reflected
2299 * in ptregs at this point, so we use r0 here.
2300 */
2301 if (check_errno && is_negated_errno(tile_regs.regs[0])) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002302 tcp->u_rval = -1;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002303 u_error = -tile_regs.regs[0];
2304 } else {
2305 tcp->u_rval = tile_regs.regs[0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002306 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002307#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002308 if (check_errno && is_negated_errno(microblaze_r3)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002309 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002310 u_error = -microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002311 }
2312 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002313 tcp->u_rval = microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002314 }
Christian Svensson492f81f2013-02-14 13:26:27 +01002315#elif defined(OR1K)
2316 if (check_errno && is_negated_errno(or1k_regs.gpr[11])) {
2317 tcp->u_rval = -1;
2318 u_error = -or1k_regs.gpr[11];
2319 }
2320 else {
2321 tcp->u_rval = or1k_regs.gpr[11];
2322 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002323#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002324 tcp->u_error = u_error;
2325 return 1;
2326}
2327
2328static void
2329dumpio(struct tcb *tcp)
2330{
2331 if (syserror(tcp))
2332 return;
2333 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
2334 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002335 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002336 return;
2337 if (sysent[tcp->scno].sys_func == printargs)
2338 return;
2339 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
2340 if (sysent[tcp->scno].sys_func == sys_read ||
2341 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002342 sysent[tcp->scno].sys_func == sys_recv ||
2343 sysent[tcp->scno].sys_func == sys_recvfrom)
2344 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
2345 else if (sysent[tcp->scno].sys_func == sys_readv)
2346 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2347 return;
2348 }
2349 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
2350 if (sysent[tcp->scno].sys_func == sys_write ||
2351 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002352 sysent[tcp->scno].sys_func == sys_send ||
2353 sysent[tcp->scno].sys_func == sys_sendto)
2354 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
2355 else if (sysent[tcp->scno].sys_func == sys_writev)
2356 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2357 return;
2358 }
2359}
2360
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002361static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002362trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002363{
2364 int sys_res;
2365 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002366 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002367 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002368
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002369 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002370 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002371 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002372
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002373#if SUPPORTED_PERSONALITIES > 1
2374 update_personality(tcp, tcp->currpers);
2375#endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002376 res = (get_regs_error ? -1 : get_syscall_result(tcp));
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002377 if (res == 1) {
2378 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01002379 res = get_error(tcp); /* returns 1 or -1 */
2380 if (res == 1) {
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01002381 if (need_fork_exec_workarounds)
2382 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01002383 if (filtered(tcp)) {
2384 goto ret;
2385 }
2386 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002387 }
2388
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002389 if (cflag) {
2390 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002391 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002392 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002393 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002394 }
2395 }
2396
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002397 /* If not in -ff mode, and printing_tcp != tcp,
2398 * then the log currently does not end with output
2399 * of _our syscall entry_, but with something else.
2400 * We need to say which syscall's return is this.
2401 *
2402 * Forced reprinting via TCB_REPRINT is used only by
2403 * "strace -ff -oLOG test/threaded_execve" corner case.
2404 * It's the only case when -ff mode needs reprinting.
2405 */
2406 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2407 tcp->flags &= ~TCB_REPRINT;
2408 printleader(tcp);
2409 if (!SCNO_IN_RANGE(tcp->scno))
2410 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2411 else
2412 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2413 }
2414 printing_tcp = tcp;
2415
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002416 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002417 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002418 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002419 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002420 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002421 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002422 tcp->flags &= ~TCB_INSYSCALL;
2423 return res;
2424 }
2425
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002426 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002427 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002428 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002429 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002430 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002431 /* FIXME: not_failing_only (IOW, option -z) is broken:
2432 * failure of syscall is known only after syscall return.
2433 * Thus we end up with something like this on, say, ENOENT:
2434 * open("doesnt_exist", O_RDONLY <unfinished ...>
2435 * {next syscall decode}
2436 * whereas the intended result is that open(...) line
2437 * is not shown at all.
2438 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002439 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002440 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002441 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2442 }
2443
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002444 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002445 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002446 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002447 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002448 qual_flags[tcp->scno] & QUAL_RAW) {
2449 if (u_error)
2450 tprintf("= -1 (errno %ld)", u_error);
2451 else
2452 tprintf("= %#lx", tcp->u_rval);
2453 }
2454 else if (!(sys_res & RVAL_NONE) && u_error) {
2455 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002456 /* Blocked signals do not interrupt any syscalls.
2457 * In this case syscalls don't return ERESTARTfoo codes.
2458 *
2459 * Deadly signals set to SIG_DFL interrupt syscalls
2460 * and kill the process regardless of which of the codes below
2461 * is returned by the interrupted syscall.
2462 * In some cases, kernel forces a kernel-generated deadly
2463 * signal to be unblocked and set to SIG_DFL (and thus cause
2464 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2465 * or SIGILL. (The alternative is to leave process spinning
2466 * forever on the faulty instruction - not useful).
2467 *
2468 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2469 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2470 * but kernel will always restart them.
2471 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002472 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002473 /* Most common type of signal-interrupted syscall exit code.
2474 * The system call will be restarted with the same arguments
2475 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2476 */
2477 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002478 break;
2479 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002480 /* Rare. For example, fork() returns this if interrupted.
2481 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2482 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002483 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002484 break;
2485 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002486 /* pause(), rt_sigsuspend() etc use this code.
2487 * SA_RESTART is ignored (assumed not set):
2488 * syscall won't restart (will return EINTR instead)
2489 * even after signal with SA_RESTART set.
2490 * However, after SIG_IGN or SIG_DFL signal it will.
2491 */
2492 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002493 break;
2494 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002495 /* Syscalls like nanosleep(), poll() which can't be
2496 * restarted with their original arguments use this
2497 * code. Kernel will execute restart_syscall() instead,
2498 * which changes arguments before restarting syscall.
2499 * SA_RESTART is ignored (assumed not set) similarly
2500 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2501 * since restart data is saved in "restart block"
2502 * in task struct, and if signal handler uses a syscall
2503 * which in turn saves another such restart block,
2504 * old data is lost and restart becomes impossible)
2505 */
2506 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002507 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002508 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002509 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002510 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002511 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002512 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002513 strerror(u_error));
2514 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002515 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002516 strerror(u_error));
2517 break;
2518 }
2519 if ((sys_res & RVAL_STR) && tcp->auxstr)
2520 tprintf(" (%s)", tcp->auxstr);
2521 }
2522 else {
2523 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002524 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002525 else {
2526 switch (sys_res & RVAL_MASK) {
2527 case RVAL_HEX:
2528 tprintf("= %#lx", tcp->u_rval);
2529 break;
2530 case RVAL_OCTAL:
2531 tprintf("= %#lo", tcp->u_rval);
2532 break;
2533 case RVAL_UDECIMAL:
2534 tprintf("= %lu", tcp->u_rval);
2535 break;
2536 case RVAL_DECIMAL:
2537 tprintf("= %ld", tcp->u_rval);
2538 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002539#if defined(LINUX_MIPSN32) || defined(X32)
2540 /*
2541 case RVAL_LHEX:
2542 tprintf("= %#llx", tcp->u_lrval);
2543 break;
2544 case RVAL_LOCTAL:
2545 tprintf("= %#llo", tcp->u_lrval);
2546 break;
2547 */
2548 case RVAL_LUDECIMAL:
2549 tprintf("= %llu", tcp->u_lrval);
2550 break;
2551 /*
2552 case RVAL_LDECIMAL:
2553 tprintf("= %lld", tcp->u_lrval);
2554 break;
2555 */
2556#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002557 default:
2558 fprintf(stderr,
2559 "invalid rval format\n");
2560 break;
2561 }
2562 }
2563 if ((sys_res & RVAL_STR) && tcp->auxstr)
2564 tprintf(" (%s)", tcp->auxstr);
2565 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002566 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002567 tv_sub(&tv, &tv, &tcp->etime);
2568 tprintf(" <%ld.%06ld>",
2569 (long) tv.tv_sec, (long) tv.tv_usec);
2570 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002571 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002572 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002573 line_ended();
2574
Denys Vlasenko3b738812011-08-22 02:06:35 +02002575 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002576 tcp->flags &= ~TCB_INSYSCALL;
2577 return 0;
2578}
2579
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002580int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002581trace_syscall(struct tcb *tcp)
2582{
2583 return exiting(tcp) ?
2584 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2585}