blob: bf94eee5e5abf7edfa759cddb7d34a9f5116b71a [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);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001435#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001436 if (upeek(tcp, 0, &scno) < 0)
1437 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01001438#elif defined(OR1K)
1439 scno = or1k_regs.gpr[11];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001440#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001441
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001442 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001443 return 1;
1444}
1445
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001446/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001447 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001448 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1449 * 1: ok, continue in trace_syscall_entering().
1450 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001451 * ("????" etc) and bail out.
1452 */
Roland McGratha4d48532005-06-08 20:45:28 +00001453static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001454syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001455{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001456 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001457#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001458 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001459 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001460 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1461 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001462 }
H.J. Lu35be5812012-04-16 13:00:01 +02001463#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001464 {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001465 long rax;
1466 if (x86_io.iov_len == sizeof(i386_regs)) {
1467 /* Sign extend from 32 bits */
1468 rax = (int32_t)i386_regs.eax;
1469 } else {
1470 /* Note: in X32 build, this truncates 64 to 32 bits */
1471 rax = x86_64_regs.rax;
1472 }
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001473 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001474 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001475 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1476 return 0;
1477 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001478 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001479#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001480 /* TODO: we already fetched PT_GPR2 in get_scno
1481 * and stored it in syscall_mode, reuse it here
1482 * instead of re-fetching?
1483 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001484 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001485 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001486 if (syscall_mode != -ENOSYS)
1487 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001488 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001489 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001490 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001491 return 0;
1492 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001493#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001494 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001495 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001496 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001497 if (m68k_d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001498 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001499 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", m68k_d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001500 return 0;
1501 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001502#elif defined(IA64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001503 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001504 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001505 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001506 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001507 if (ia32 && ia64_r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001508 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001509 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", ia64_r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001510 return 0;
1511 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001512#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001513 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001514 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001515 if (cris_r10 != -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 (r10 = %ld)\n", cris_r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001518 return 0;
1519 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001520#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001521 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001522 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001523 if (microblaze_r3 != -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 (r3 = %ld)\n", microblaze_r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001526 return 0;
1527 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001528#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001529 return 1;
1530}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001531
Denys Vlasenko146b9442012-03-18 22:10:48 +01001532static void
1533internal_fork(struct tcb *tcp)
1534{
1535#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1536# define ARG_FLAGS 1
1537#else
1538# define ARG_FLAGS 0
1539#endif
1540#ifndef CLONE_UNTRACED
1541# define CLONE_UNTRACED 0x00800000
1542#endif
1543 if ((ptrace_setoptions
1544 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1545 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1546 return;
1547
1548 if (!followfork)
1549 return;
1550
1551 if (entering(tcp)) {
1552 /*
1553 * We won't see the new child if clone is called with
1554 * CLONE_UNTRACED, so we keep the same logic with that option
1555 * and don't trace it.
1556 */
1557 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1558 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1559 return;
1560 setbpt(tcp);
1561 } else {
1562 if (tcp->flags & TCB_BPTSET)
1563 clearbpt(tcp);
1564 }
1565}
1566
1567#if defined(TCB_WAITEXECVE)
1568static void
1569internal_exec(struct tcb *tcp)
1570{
1571 /* Maybe we have post-execve SIGTRAP suppressed? */
1572 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1573 return; /* yes, no need to do anything */
1574
1575 if (exiting(tcp) && syserror(tcp))
1576 /* Error in execve, no post-execve SIGTRAP expected */
1577 tcp->flags &= ~TCB_WAITEXECVE;
1578 else
1579 tcp->flags |= TCB_WAITEXECVE;
1580}
1581#endif
1582
1583static void
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001584syscall_fixup_for_fork_exec(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001585{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001586 /*
1587 * We must always trace a few critical system calls in order to
1588 * correctly support following forks in the presence of tracing
1589 * qualifiers.
1590 */
1591 int (*func)();
1592
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001593 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001594 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001595
1596 func = sysent[tcp->scno].sys_func;
1597
1598 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001599 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001600 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001601 ) {
1602 internal_fork(tcp);
1603 return;
1604 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001605
Denys Vlasenko84703742012-02-25 02:38:52 +01001606#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001607 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001608# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001609 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001610# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001611 ) {
1612 internal_exec(tcp);
1613 return;
1614 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001615#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001616}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001617
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001618/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001619static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001620get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001621{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001622 int i, nargs;
1623
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001624 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001625 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001626 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001627 nargs = tcp->u_nargs = MAX_ARGS;
1628
Denys Vlasenko523635f2012-02-25 02:44:25 +01001629#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001630 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001631 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1632 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001633#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001634 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001635 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1636 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001637#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001638 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001639 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001640 long rbs_end;
1641 /* be backwards compatible with kernel < 2.4.4... */
1642# ifndef PT_RBS_END
1643# define PT_RBS_END PT_AR_BSP
1644# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001645
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001646 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1647 return -1;
1648 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001649 return -1;
1650
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001651 sof = (cfm >> 0) & 0x7f;
1652 sol = (cfm >> 7) & 0x7f;
1653 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1654
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001655 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001656 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1657 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1658 return -1;
1659 }
1660 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001661 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1662 PT_R9 /* ECX = out1 */,
1663 PT_R10 /* EDX = out2 */,
1664 PT_R14 /* ESI = out3 */,
1665 PT_R15 /* EDI = out4 */,
1666 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001667
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001668 for (i = 0; i < nargs; ++i) {
1669 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1670 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001671 /* truncate away IVE sign-extension */
1672 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001673 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001674 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001675#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001676 /* N32 and N64 both use up to six registers. */
1677 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001678
1679 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1680 return -1;
1681
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001682 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001683 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001684# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001685 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001686# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001687 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001688#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001689 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001690 long sp;
1691
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001692 if (upeek(tcp, REG_SP, &sp) < 0)
1693 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001694 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001695 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1696 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001697 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001698 (char *)(tcp->u_arg + 4));
1699 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001700 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001701 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001702 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001703 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001704#elif defined(POWERPC)
1705# ifndef PT_ORIG_R3
1706# define PT_ORIG_R3 34
1707# endif
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, (i==0) ?
1710 (sizeof(unsigned long) * PT_ORIG_R3) :
1711 ((i+PT_R3) * sizeof(unsigned long)),
1712 &tcp->u_arg[i]) < 0)
1713 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001714 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001715#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001716 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001717 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001718#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001719 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001720 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1721 return -1;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001722#elif defined(ARM) || defined(AARCH64)
1723# if defined(AARCH64)
1724 if (tcp->currpers == 1)
1725 for (i = 0; i < nargs; ++i)
1726 tcp->u_arg[i] = aarch64_regs.regs[i];
1727 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001728# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001729 for (i = 0; i < nargs; ++i)
Denys Vlasenko401374e2013-02-06 18:24:39 +01001730 tcp->u_arg[i] = arm_regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001731#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001732 (void)i;
1733 (void)nargs;
1734 tcp->u_arg[0] = regs.r12;
1735 tcp->u_arg[1] = regs.r11;
1736 tcp->u_arg[2] = regs.r10;
1737 tcp->u_arg[3] = regs.r9;
1738 tcp->u_arg[4] = regs.r5;
1739 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001740#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001741 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 +02001742
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001743 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001744 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1745 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001746#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001747 static const int syscall_regs[MAX_ARGS] = {
1748 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1749 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001750 };
1751
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001752 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001753 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001754 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001755#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001756 int i;
1757 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001758 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001759
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001760 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001761 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1762 return -1;
Denys Vlasenko6cf36052013-02-15 15:01:38 +01001763#elif defined(I386)
1764 (void)i;
1765 (void)nargs;
1766 tcp->u_arg[0] = i386_regs.ebx;
1767 tcp->u_arg[1] = i386_regs.ecx;
1768 tcp->u_arg[2] = i386_regs.edx;
1769 tcp->u_arg[3] = i386_regs.esi;
1770 tcp->u_arg[4] = i386_regs.edi;
1771 tcp->u_arg[5] = i386_regs.ebp;
H.J. Lu35be5812012-04-16 13:00:01 +02001772#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001773 (void)i;
1774 (void)nargs;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001775 if (x86_io.iov_len != sizeof(i386_regs)) {
1776 /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001777 tcp->u_arg[0] = x86_64_regs.rdi;
1778 tcp->u_arg[1] = x86_64_regs.rsi;
1779 tcp->u_arg[2] = x86_64_regs.rdx;
1780 tcp->u_arg[3] = x86_64_regs.r10;
1781 tcp->u_arg[4] = x86_64_regs.r8;
1782 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001783# ifdef X32
1784 tcp->ext_arg[0] = x86_64_regs.rdi;
1785 tcp->ext_arg[1] = x86_64_regs.rsi;
1786 tcp->ext_arg[2] = x86_64_regs.rdx;
1787 tcp->ext_arg[3] = x86_64_regs.r10;
1788 tcp->ext_arg[4] = x86_64_regs.r8;
1789 tcp->ext_arg[5] = x86_64_regs.r9;
1790# endif
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001791 } else {
1792 /* i386 ABI */
Denys Vlasenko6cf36052013-02-15 15:01:38 +01001793 /* Zero-extend from 32 bits */
1794 /* Use widen_to_long(tcp->u_arg[N]) in syscall handlers
1795 * if you need to use *sign-extended* parameter.
1796 */
1797 tcp->u_arg[0] = (long)(uint32_t)i386_regs.ebx;
1798 tcp->u_arg[1] = (long)(uint32_t)i386_regs.ecx;
1799 tcp->u_arg[2] = (long)(uint32_t)i386_regs.edx;
1800 tcp->u_arg[3] = (long)(uint32_t)i386_regs.esi;
1801 tcp->u_arg[4] = (long)(uint32_t)i386_regs.edi;
1802 tcp->u_arg[5] = (long)(uint32_t)i386_regs.ebp;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001803 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001804#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001805 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001806 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1807 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001808#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001809 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001810 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001811 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001812 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001813
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001814 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001815 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1816 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001817#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001818 for (i = 0; i < nargs; ++i)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001819 tcp->u_arg[i] = tile_regs.regs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001820#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001821 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001822 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1823 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01001824#elif defined(OR1K)
1825 (void)nargs;
1826 for (i = 0; i < 6; ++i)
1827 tcp->u_arg[i] = or1k_regs.gpr[3 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001828#else /* Other architecture (32bits specific) */
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*4, &tcp->u_arg[i]) < 0)
1831 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001832#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001833 return 1;
1834}
1835
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001836static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001837trace_syscall_entering(struct tcb *tcp)
1838{
1839 int res, scno_good;
1840
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001841#if defined TCB_WAITEXECVE
1842 if (tcp->flags & TCB_WAITEXECVE) {
1843 /* This is the post-execve SIGTRAP. */
1844 tcp->flags &= ~TCB_WAITEXECVE;
1845 return 0;
1846 }
1847#endif
1848
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001849 scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001850 if (res == 0)
1851 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001852 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001853 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001854 if (res == 0)
1855 return res;
1856 if (res == 1)
1857 res = get_syscall_args(tcp);
1858 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001859
1860 if (res != 1) {
1861 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001862 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001863 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001864 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001865 tprintf("syscall_%lu(", tcp->scno);
1866 else
1867 tprintf("%s(", sysent[tcp->scno].sys_name);
1868 /*
1869 * " <unavailable>" will be added later by the code which
1870 * detects ptrace errors.
1871 */
1872 goto ret;
1873 }
1874
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001875#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1876 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001877# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001878 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001879 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001880 break;
1881 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001882# endif
1883# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001884 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001885 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001886 break;
1887 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001888# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001889 break;
1890 }
1891#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1892
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001893 if (need_fork_exec_workarounds)
1894 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001895
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001896 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001897 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1898 (tracing_paths && !pathtrace_match(tcp))) {
1899 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1900 return 0;
1901 }
1902
1903 tcp->flags &= ~TCB_FILTERED;
1904
1905 if (cflag == CFLAG_ONLY_STATS) {
1906 res = 0;
1907 goto ret;
1908 }
1909
1910 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001911 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001912 tprintf("syscall_%lu(", tcp->scno);
1913 else
1914 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001915 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001916 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1917 sysent[tcp->scno].sys_func != sys_exit))
1918 res = printargs(tcp);
1919 else
1920 res = (*sysent[tcp->scno].sys_func)(tcp);
1921
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001922 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001923 ret:
1924 tcp->flags |= TCB_INSYSCALL;
1925 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001926 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001927 gettimeofday(&tcp->etime, NULL);
1928 return res;
1929}
1930
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001931/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001932 * 1: ok, continue in trace_syscall_exiting().
1933 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001934 * ("????" etc) and bail out.
1935 */
1936static int
1937get_syscall_result(struct tcb *tcp)
1938{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001939#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001940 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1941 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001942#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001943# define SO_MASK 0x10000000
1944 {
1945 long flags;
1946 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1947 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001948 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001949 return -1;
1950 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001951 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001952 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001953#elif defined(AVR32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001954 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001955#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001956 if (upeek(tcp, PT_R0, &bfin_r0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001957 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001958#elif defined(I386)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001959 /* already done by get_regs */
H.J. Lu35be5812012-04-16 13:00:01 +02001960#elif defined(X86_64) || defined(X32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001961 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001962#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001963# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001964 long psr;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001965 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1966 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001967 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001968 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001969 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001970 return -1;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001971#elif defined(ARM)
1972 /* already done by get_regs */
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001973#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001974 /* register reading already done by get_regs */
1975
1976 /* Used to do this, but we did it on syscall entry already: */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001977 /* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
1978 * else it's personality 0.
1979 */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001980 /*update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));*/
Denys Vlasenko523635f2012-02-25 02:44:25 +01001981#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001982 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001983 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001984#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001985 unsigned long long regs[38];
1986
1987 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1988 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001989 mips_a3 = regs[REG_A3];
1990 mips_r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001991#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001992 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001993 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001994 if (upeek(tcp, REG_V0, &mips_r2) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001995 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001996#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001997 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001998 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001999 if (upeek(tcp, REG_R0, &alpha_r0) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002000 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002001#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002002 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002003#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002004 if (upeek(tcp, PT_GR28, &hppa_r28) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002005 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002006#elif defined(SH)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002007 /* new syscall ABI returns result in R0 */
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002008 if (upeek(tcp, 4*REG_REG0, (long *)&sh_r0) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002009 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002010#elif defined(SH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002011 /* ABI defines result returned in r9 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002012 if (upeek(tcp, REG_GENERAL(9), (long *)&sh64_r9) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002013 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002014#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002015 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002016 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002017#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002018 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002019#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002020 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002021 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01002022#elif defined(OR1K)
2023 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002024#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002025 return 1;
2026}
2027
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002028/* Called at each syscall exit */
2029static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002030syscall_fixup_on_sysexit(struct tcb *tcp)
2031{
Denys Vlasenko523635f2012-02-25 02:44:25 +01002032#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002033 if (syscall_mode != -ENOSYS)
2034 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02002035 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002036 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
2037 /*
2038 * Return from execve.
2039 * Fake a return value of zero. We leave the TCB_WAITEXECVE
2040 * flag set for the post-execve SIGTRAP to see and reset.
2041 */
2042 gpr2 = 0;
2043 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002044#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002045}
2046
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002047/*
2048 * Check the syscall return value register value for whether it is
2049 * a negated errno code indicating an error, or a success return value.
2050 */
2051static inline int
2052is_negated_errno(unsigned long int val)
2053{
2054 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002055#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01002056 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002057 val = (unsigned int) val;
2058 max = (unsigned int) max;
2059 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002060#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002061 return val > max;
2062}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002063
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002064#if defined(X32)
2065static inline int
2066is_negated_errno_x32(unsigned long long val)
2067{
2068 unsigned long long max = -(long long) nerrnos;
2069 /*
2070 * current_wordsize is 4 even in personality 0 (native X32)
2071 * but truncation _must not_ be done in it.
2072 * can't check current_wordsize here!
2073 */
2074 if (current_personality != 0) {
2075 val = (uint32_t) val;
2076 max = (uint32_t) max;
2077 }
2078 return val > max;
2079}
2080#endif
2081
Denys Vlasenko907735a2012-03-21 00:23:16 +01002082/* Returns:
2083 * 1: ok, continue in trace_syscall_exiting().
2084 * -1: error, trace_syscall_exiting() should print error indicator
2085 * ("????" etc) and bail out.
2086 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002087static int
2088get_error(struct tcb *tcp)
2089{
2090 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002091 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002092 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002093 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
2094 check_errno = 0;
2095 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002096#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002097 if (check_errno && is_negated_errno(gpr2)) {
2098 tcp->u_rval = -1;
2099 u_error = -gpr2;
2100 }
2101 else {
2102 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002103 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002104#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002105 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002106 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002107 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002108 }
2109 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002110 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002111 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002112#elif defined(X86_64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002113 long rax;
2114 if (x86_io.iov_len == sizeof(i386_regs)) {
2115 /* Sign extend from 32 bits */
2116 rax = (int32_t)i386_regs.eax;
2117 } else {
2118 rax = x86_64_regs.rax;
2119 }
2120 if (check_errno && is_negated_errno(rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002121 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002122 u_error = -rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002123 }
2124 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002125 tcp->u_rval = rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002126 }
2127#elif defined(X32)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002128 /* In X32, return value is 64-bit (llseek uses one).
2129 * Using merely "long rax" would not work.
2130 */
2131 long long rax;
2132 if (x86_io.iov_len == sizeof(i386_regs)) {
2133 /* Sign extend from 32 bits */
2134 rax = (int32_t)i386_regs.eax;
2135 } else {
2136 rax = x86_64_regs.rax;
2137 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002138 /* Careful: is_negated_errno() works only on longs */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002139 if (check_errno && is_negated_errno_x32(rax)) {
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002140 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002141 u_error = -rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002142 }
2143 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002144 tcp->u_rval = rax; /* truncating */
2145 tcp->u_lrval = rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002146 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002147#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002148 if (ia32) {
2149 int err;
2150
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002151 err = (int)ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002152 if (check_errno && is_negated_errno(err)) {
2153 tcp->u_rval = -1;
2154 u_error = -err;
2155 }
2156 else {
2157 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002158 }
2159 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002160 if (check_errno && ia64_r10) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002161 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002162 u_error = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002163 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002164 tcp->u_rval = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002165 }
2166 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002167#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002168 if (check_errno && mips_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002169 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002170 u_error = mips_r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002171 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002172 tcp->u_rval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002173# if defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002174 tcp->u_lrval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002175# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002176 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002177#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002178 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002179 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002180 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002181 }
2182 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002183 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002184 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002185#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002186 if (check_errno && is_negated_errno(m68k_d0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002187 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002188 u_error = -m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002189 }
2190 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002191 tcp->u_rval = m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002192 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002193#elif defined(ARM) || defined(AARCH64)
2194# if defined(AARCH64)
2195 if (tcp->currpers == 1) {
2196 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2197 tcp->u_rval = -1;
2198 u_error = -aarch64_regs.regs[0];
2199 }
2200 else {
2201 tcp->u_rval = aarch64_regs.regs[0];
2202 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002203 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002204 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01002205# endif
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002206 {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002207 if (check_errno && is_negated_errno(arm_regs.ARM_r0)) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002208 tcp->u_rval = -1;
Denys Vlasenko401374e2013-02-06 18:24:39 +01002209 u_error = -arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002210 }
2211 else {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002212 tcp->u_rval = arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002213 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002214 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002215#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002216 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
2217 tcp->u_rval = -1;
2218 u_error = -regs.r12;
2219 }
2220 else {
2221 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002222 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002223#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002224 if (check_errno && is_negated_errno(bfin_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002225 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002226 u_error = -bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002227 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002228 tcp->u_rval = bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002229 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002230#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002231 if (check_errno && alpha_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002232 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002233 u_error = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002234 }
2235 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002236 tcp->u_rval = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002237 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002238#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002239 if (check_errno && regs.psr & PSR_C) {
2240 tcp->u_rval = -1;
2241 u_error = regs.u_regs[U_REG_O0];
2242 }
2243 else {
2244 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002245 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002246#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002247 if (check_errno && regs.tstate & 0x1100000000UL) {
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(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002255 if (check_errno && is_negated_errno(hppa_r28)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002256 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002257 u_error = -hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002258 }
2259 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002260 tcp->u_rval = hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002261 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002262#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002263 if (check_errno && is_negated_errno(sh_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002264 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002265 u_error = -sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002266 }
2267 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002268 tcp->u_rval = sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002269 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002270#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002271 if (check_errno && is_negated_errno(sh64_r9)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002272 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002273 u_error = -sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002274 }
2275 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002276 tcp->u_rval = sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002277 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002278#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002279 if (check_errno && cris_r10 && (unsigned) -cris_r10 < nerrnos) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002280 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002281 u_error = -cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002282 }
2283 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002284 tcp->u_rval = cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002285 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002286#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002287 /*
2288 * The standard tile calling convention returns the value (or negative
2289 * errno) in r0, and zero (or positive errno) in r1.
2290 * Until at least kernel 3.8, however, the r1 value is not reflected
2291 * in ptregs at this point, so we use r0 here.
2292 */
2293 if (check_errno && is_negated_errno(tile_regs.regs[0])) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002294 tcp->u_rval = -1;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002295 u_error = -tile_regs.regs[0];
2296 } else {
2297 tcp->u_rval = tile_regs.regs[0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002298 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002299#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002300 if (check_errno && is_negated_errno(microblaze_r3)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002301 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002302 u_error = -microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002303 }
2304 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002305 tcp->u_rval = microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002306 }
Christian Svensson492f81f2013-02-14 13:26:27 +01002307#elif defined(OR1K)
2308 if (check_errno && is_negated_errno(or1k_regs.gpr[11])) {
2309 tcp->u_rval = -1;
2310 u_error = -or1k_regs.gpr[11];
2311 }
2312 else {
2313 tcp->u_rval = or1k_regs.gpr[11];
2314 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002315#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002316 tcp->u_error = u_error;
2317 return 1;
2318}
2319
2320static void
2321dumpio(struct tcb *tcp)
2322{
2323 if (syserror(tcp))
2324 return;
2325 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
2326 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002327 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002328 return;
2329 if (sysent[tcp->scno].sys_func == printargs)
2330 return;
2331 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
2332 if (sysent[tcp->scno].sys_func == sys_read ||
2333 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002334 sysent[tcp->scno].sys_func == sys_recv ||
2335 sysent[tcp->scno].sys_func == sys_recvfrom)
2336 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
2337 else if (sysent[tcp->scno].sys_func == sys_readv)
2338 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2339 return;
2340 }
2341 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
2342 if (sysent[tcp->scno].sys_func == sys_write ||
2343 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002344 sysent[tcp->scno].sys_func == sys_send ||
2345 sysent[tcp->scno].sys_func == sys_sendto)
2346 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
2347 else if (sysent[tcp->scno].sys_func == sys_writev)
2348 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2349 return;
2350 }
2351}
2352
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002353static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002354trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002355{
2356 int sys_res;
2357 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002358 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002359 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002360
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002361 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002362 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002363 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002364
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002365#if SUPPORTED_PERSONALITIES > 1
2366 update_personality(tcp, tcp->currpers);
2367#endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002368 res = (get_regs_error ? -1 : get_syscall_result(tcp));
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002369 if (res == 1) {
2370 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01002371 res = get_error(tcp); /* returns 1 or -1 */
2372 if (res == 1) {
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01002373 if (need_fork_exec_workarounds)
2374 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01002375 if (filtered(tcp)) {
2376 goto ret;
2377 }
2378 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002379 }
2380
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002381 if (cflag) {
2382 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002383 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002384 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002385 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002386 }
2387 }
2388
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002389 /* If not in -ff mode, and printing_tcp != tcp,
2390 * then the log currently does not end with output
2391 * of _our syscall entry_, but with something else.
2392 * We need to say which syscall's return is this.
2393 *
2394 * Forced reprinting via TCB_REPRINT is used only by
2395 * "strace -ff -oLOG test/threaded_execve" corner case.
2396 * It's the only case when -ff mode needs reprinting.
2397 */
2398 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2399 tcp->flags &= ~TCB_REPRINT;
2400 printleader(tcp);
2401 if (!SCNO_IN_RANGE(tcp->scno))
2402 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2403 else
2404 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2405 }
2406 printing_tcp = tcp;
2407
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002408 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002409 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002410 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002411 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002412 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002413 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002414 tcp->flags &= ~TCB_INSYSCALL;
2415 return res;
2416 }
2417
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002418 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002419 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002420 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002421 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002422 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002423 /* FIXME: not_failing_only (IOW, option -z) is broken:
2424 * failure of syscall is known only after syscall return.
2425 * Thus we end up with something like this on, say, ENOENT:
2426 * open("doesnt_exist", O_RDONLY <unfinished ...>
2427 * {next syscall decode}
2428 * whereas the intended result is that open(...) line
2429 * is not shown at all.
2430 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002431 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002432 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002433 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2434 }
2435
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002436 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002437 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002438 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002439 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002440 qual_flags[tcp->scno] & QUAL_RAW) {
2441 if (u_error)
2442 tprintf("= -1 (errno %ld)", u_error);
2443 else
2444 tprintf("= %#lx", tcp->u_rval);
2445 }
2446 else if (!(sys_res & RVAL_NONE) && u_error) {
2447 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002448 /* Blocked signals do not interrupt any syscalls.
2449 * In this case syscalls don't return ERESTARTfoo codes.
2450 *
2451 * Deadly signals set to SIG_DFL interrupt syscalls
2452 * and kill the process regardless of which of the codes below
2453 * is returned by the interrupted syscall.
2454 * In some cases, kernel forces a kernel-generated deadly
2455 * signal to be unblocked and set to SIG_DFL (and thus cause
2456 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2457 * or SIGILL. (The alternative is to leave process spinning
2458 * forever on the faulty instruction - not useful).
2459 *
2460 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2461 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2462 * but kernel will always restart them.
2463 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002464 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002465 /* Most common type of signal-interrupted syscall exit code.
2466 * The system call will be restarted with the same arguments
2467 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2468 */
2469 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002470 break;
2471 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002472 /* Rare. For example, fork() returns this if interrupted.
2473 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2474 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002475 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002476 break;
2477 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002478 /* pause(), rt_sigsuspend() etc use this code.
2479 * SA_RESTART is ignored (assumed not set):
2480 * syscall won't restart (will return EINTR instead)
2481 * even after signal with SA_RESTART set.
2482 * However, after SIG_IGN or SIG_DFL signal it will.
2483 */
2484 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002485 break;
2486 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002487 /* Syscalls like nanosleep(), poll() which can't be
2488 * restarted with their original arguments use this
2489 * code. Kernel will execute restart_syscall() instead,
2490 * which changes arguments before restarting syscall.
2491 * SA_RESTART is ignored (assumed not set) similarly
2492 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2493 * since restart data is saved in "restart block"
2494 * in task struct, and if signal handler uses a syscall
2495 * which in turn saves another such restart block,
2496 * old data is lost and restart becomes impossible)
2497 */
2498 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002499 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002500 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002501 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002502 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002503 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002504 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002505 strerror(u_error));
2506 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002507 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002508 strerror(u_error));
2509 break;
2510 }
2511 if ((sys_res & RVAL_STR) && tcp->auxstr)
2512 tprintf(" (%s)", tcp->auxstr);
2513 }
2514 else {
2515 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002516 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002517 else {
2518 switch (sys_res & RVAL_MASK) {
2519 case RVAL_HEX:
2520 tprintf("= %#lx", tcp->u_rval);
2521 break;
2522 case RVAL_OCTAL:
2523 tprintf("= %#lo", tcp->u_rval);
2524 break;
2525 case RVAL_UDECIMAL:
2526 tprintf("= %lu", tcp->u_rval);
2527 break;
2528 case RVAL_DECIMAL:
2529 tprintf("= %ld", tcp->u_rval);
2530 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002531#if defined(LINUX_MIPSN32) || defined(X32)
2532 /*
2533 case RVAL_LHEX:
2534 tprintf("= %#llx", tcp->u_lrval);
2535 break;
2536 case RVAL_LOCTAL:
2537 tprintf("= %#llo", tcp->u_lrval);
2538 break;
2539 */
2540 case RVAL_LUDECIMAL:
2541 tprintf("= %llu", tcp->u_lrval);
2542 break;
2543 /*
2544 case RVAL_LDECIMAL:
2545 tprintf("= %lld", tcp->u_lrval);
2546 break;
2547 */
2548#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002549 default:
2550 fprintf(stderr,
2551 "invalid rval format\n");
2552 break;
2553 }
2554 }
2555 if ((sys_res & RVAL_STR) && tcp->auxstr)
2556 tprintf(" (%s)", tcp->auxstr);
2557 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002558 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002559 tv_sub(&tv, &tv, &tcp->etime);
2560 tprintf(" <%ld.%06ld>",
2561 (long) tv.tv_sec, (long) tv.tv_usec);
2562 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002563 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002564 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002565 line_ended();
2566
Denys Vlasenko3b738812011-08-22 02:06:35 +02002567 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002568 tcp->flags &= ~TCB_INSYSCALL;
2569 return 0;
2570}
2571
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002572int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002573trace_syscall(struct tcb *tcp)
2574{
2575 return exiting(tcp) ?
2576 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2577}