blob: b0104d09266a7ea1f808bb07819a5ccfb184911e [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
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000081#ifndef ERESTARTSYS
Denys Vlasenko523635f2012-02-25 02:44:25 +010082# define ERESTARTSYS 512
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000083#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010084#ifndef ERESTARTNOINTR
Denys Vlasenko523635f2012-02-25 02:44:25 +010085# define ERESTARTNOINTR 513
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000086#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010087#ifndef ERESTARTNOHAND
88# define ERESTARTNOHAND 514 /* restart if no handler */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000089#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010090#ifndef ERESTART_RESTARTBLOCK
Denys Vlasenko523635f2012-02-25 02:44:25 +010091# define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
Roland McGrath9c555e72003-07-09 09:47:59 +000092#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010093
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000094#ifndef NSIG
Denys Vlasenko523635f2012-02-25 02:44:25 +010095# warning: NSIG is not defined, using 32
96# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000097#endif
98#ifdef ARM
Denys Vlasenko041b3ee2011-08-18 12:48:56 +020099/* Ugh. Is this really correct? ARM has no RT signals?! */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100100# undef NSIG
101# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000103
104#include "syscall.h"
105
106/* Define these shorthand notations to simplify the syscallent files. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000107#define TD TRACE_DESC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000108#define TF TRACE_FILE
109#define TI TRACE_IPC
110#define TN TRACE_NETWORK
111#define TP TRACE_PROCESS
112#define TS TRACE_SIGNAL
Namhyung Kim96792962012-10-24 11:41:57 +0900113#define TM TRACE_MEMORY
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000114#define NF SYSCALL_NEVER_FAILS
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200115#define MA MAX_ARGS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000116
Roland McGrathee36ce12004-09-04 03:53:10 +0000117static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118#include "syscallent.h"
119};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120
121#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000122static const struct sysent sysent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100123# include "syscallent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000124};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200125#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000126
127#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000128static const struct sysent sysent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100129# include "syscallent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200131#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000132
133/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000134#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000135#undef TF
136#undef TI
137#undef TN
138#undef TP
139#undef TS
Namhyung Kim96792962012-10-24 11:41:57 +0900140#undef TM
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000141#undef NF
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200142#undef MA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000143
Denys Vlasenko39fca622011-08-20 02:12:33 +0200144/*
145 * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
146 * program `ioctlsort', such that the list is sorted by the `code' field.
147 * This has the side-effect of resolving the _IO.. macros into
148 * plain integers, eliminating the need to include here everything
149 * in "/usr/include".
150 */
151
Roland McGrathee36ce12004-09-04 03:53:10 +0000152static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000153#include "errnoent.h"
154};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200155static const char *const signalent0[] = {
156#include "signalent.h"
157};
158static const struct ioctlent ioctlent0[] = {
159#include "ioctlent.h"
160};
161enum { nsyscalls0 = ARRAY_SIZE(sysent0) };
162enum { nerrnos0 = ARRAY_SIZE(errnoent0) };
163enum { nsignals0 = ARRAY_SIZE(signalent0) };
164enum { nioctlents0 = ARRAY_SIZE(ioctlent0) };
165int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000166
167#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000168static const char *const errnoent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100169# include "errnoent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000170};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200171static const char *const signalent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100172# include "signalent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200173};
174static const struct ioctlent ioctlent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100175# include "ioctlent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200176};
177enum { nsyscalls1 = ARRAY_SIZE(sysent1) };
178enum { nerrnos1 = ARRAY_SIZE(errnoent1) };
179enum { nsignals1 = ARRAY_SIZE(signalent1) };
180enum { nioctlents1 = ARRAY_SIZE(ioctlent1) };
181int qual_flags1[MAX_QUALS];
182#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000183
184#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000185static const char *const errnoent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100186# include "errnoent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000187};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200188static const char *const signalent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100189# include "signalent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200190};
191static const struct ioctlent ioctlent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100192# include "ioctlent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200193};
194enum { nsyscalls2 = ARRAY_SIZE(sysent2) };
195enum { nerrnos2 = ARRAY_SIZE(errnoent2) };
196enum { nsignals2 = ARRAY_SIZE(signalent2) };
197enum { nioctlents2 = ARRAY_SIZE(ioctlent2) };
198int qual_flags2[MAX_QUALS];
199#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000200
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100201const struct sysent *sysent = sysent0;
202const char *const *errnoent = errnoent0;
203const char *const *signalent = signalent0;
204const struct ioctlent *ioctlent = ioctlent0;
205unsigned nsyscalls = nsyscalls0;
206unsigned nerrnos = nerrnos0;
207unsigned nsignals = nsignals0;
208unsigned nioctlents = nioctlents0;
209int *qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000210
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100211#if SUPPORTED_PERSONALITIES > 1
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000212int current_personality;
213
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000214const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
215 PERSONALITY0_WORDSIZE,
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000216 PERSONALITY1_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100217# if SUPPORTED_PERSONALITIES > 2
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000218 PERSONALITY2_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100219# endif
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200220};
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000221
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200222void
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000223set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000224{
225 switch (personality) {
226 case 0:
227 errnoent = errnoent0;
228 nerrnos = nerrnos0;
229 sysent = sysent0;
230 nsyscalls = nsyscalls0;
231 ioctlent = ioctlent0;
232 nioctlents = nioctlents0;
233 signalent = signalent0;
234 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000235 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000236 break;
237
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000238 case 1:
239 errnoent = errnoent1;
240 nerrnos = nerrnos1;
241 sysent = sysent1;
242 nsyscalls = nsyscalls1;
243 ioctlent = ioctlent1;
244 nioctlents = nioctlents1;
245 signalent = signalent1;
246 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000247 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000248 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000249
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100250# if SUPPORTED_PERSONALITIES >= 3
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000251 case 2:
252 errnoent = errnoent2;
253 nerrnos = nerrnos2;
254 sysent = sysent2;
255 nsyscalls = nsyscalls2;
256 ioctlent = ioctlent2;
257 nioctlents = nioctlents2;
258 signalent = signalent2;
259 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000260 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000261 break;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100262# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000263 }
264
265 current_personality = personality;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000266}
267
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000268static void
269update_personality(struct tcb *tcp, int personality)
270{
271 if (personality == current_personality)
272 return;
273 set_personality(personality);
274
275 if (personality == tcp->currpers)
276 return;
277 tcp->currpers = personality;
278
H.J. Lu35be5812012-04-16 13:00:01 +0200279# if defined(POWERPC64)
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000280 if (!qflag) {
281 static const char *const names[] = {"64 bit", "32 bit"};
282 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
283 tcp->pid, names[personality]);
284 }
H.J. Lu35be5812012-04-16 13:00:01 +0200285# elif defined(X86_64)
286 if (!qflag) {
287 static const char *const names[] = {"64 bit", "32 bit", "x32"};
288 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
289 tcp->pid, names[personality]);
290 }
H.J. Lu085e4282012-04-17 11:05:04 -0700291# elif defined(X32)
292 if (!qflag) {
293 static const char *const names[] = {"x32", "32 bit"};
294 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
295 tcp->pid, names[personality]);
296 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000297# elif defined(AARCH64)
298 if (!qflag) {
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100299 static const char *const names[] = {"32-bit", "AArch64"};
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000300 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
301 tcp->pid, names[personality]);
302 }
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100303# elif defined(TILE)
304 if (!qflag) {
305 static const char *const names[] = {"64-bit", "32-bit"};
306 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
307 tcp->pid, names[personality]);
308 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100309# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000310}
311#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000312
Roland McGrath9797ceb2002-12-30 10:23:00 +0000313static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000314
Roland McGrathe10e62a2004-09-04 04:20:43 +0000315static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000316 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000317 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000318 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000319 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000320} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000321 { QUAL_TRACE, "trace", qual_syscall, "system call" },
322 { QUAL_TRACE, "t", qual_syscall, "system call" },
323 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
324 { QUAL_ABBREV, "a", qual_syscall, "system call" },
325 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
326 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
327 { QUAL_RAW, "raw", qual_syscall, "system call" },
328 { QUAL_RAW, "x", qual_syscall, "system call" },
329 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
330 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
331 { QUAL_SIGNAL, "s", qual_signal, "signal" },
332 { QUAL_FAULT, "fault", qual_fault, "fault" },
333 { QUAL_FAULT, "faults", qual_fault, "fault" },
334 { QUAL_FAULT, "m", qual_fault, "fault" },
335 { QUAL_READ, "read", qual_desc, "descriptor" },
336 { QUAL_READ, "reads", qual_desc, "descriptor" },
337 { QUAL_READ, "r", qual_desc, "descriptor" },
338 { QUAL_WRITE, "write", qual_desc, "descriptor" },
339 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
340 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000341 { 0, NULL, NULL, NULL },
342};
343
Roland McGrath9797ceb2002-12-30 10:23:00 +0000344static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000345qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000346{
Roland McGrath138c6a32006-01-12 09:50:49 +0000347 if (pers == 0 || pers < 0) {
348 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000349 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000350 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000351 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000352 }
353
354#if SUPPORTED_PERSONALITIES >= 2
355 if (pers == 1 || pers < 0) {
356 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000357 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000358 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000359 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000360 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100361#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000362
363#if SUPPORTED_PERSONALITIES >= 3
364 if (pers == 2 || pers < 0) {
365 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000366 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000367 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000368 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000369 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100370#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000371}
372
373static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000374qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000375{
376 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000377 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000378
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100379 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000380 int i = string_to_uint(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000381 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000382 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000383 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000384 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000385 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000386 for (i = 0; i < nsyscalls0; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000387 if (sysent0[i].sys_name &&
388 strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000389 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000390 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000391 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000392
393#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000394 for (i = 0; i < nsyscalls1; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000395 if (sysent1[i].sys_name &&
396 strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000397 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000398 rc = 0;
399 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100400#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000401
402#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000403 for (i = 0; i < nsyscalls2; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000404 if (sysent2[i].sys_name &&
405 strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000406 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000407 rc = 0;
408 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100409#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000410
Roland McGrathfe6b3522005-02-02 04:40:11 +0000411 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000412}
413
414static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000415qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000416{
417 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000418
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100419 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000420 int signo = string_to_uint(s);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000421 if (signo < 0 || signo >= MAX_QUALS)
422 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000423 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000424 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000425 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000426 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000427 s += 3;
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100428 for (i = 0; i <= NSIG; i++) {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000429 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000430 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000431 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000432 }
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100433 }
Roland McGrath76421df2005-02-02 03:51:18 +0000434 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000435}
436
437static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000438qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000439{
440 return -1;
441}
442
443static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000444qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000445{
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100446 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000447 int desc = string_to_uint(s);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000448 if (desc < 0 || desc >= MAX_QUALS)
449 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000450 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000451 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000452 }
453 return -1;
454}
455
456static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000457lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000458{
459 if (strcmp(s, "file") == 0)
460 return TRACE_FILE;
461 if (strcmp(s, "ipc") == 0)
462 return TRACE_IPC;
463 if (strcmp(s, "network") == 0)
464 return TRACE_NETWORK;
465 if (strcmp(s, "process") == 0)
466 return TRACE_PROCESS;
467 if (strcmp(s, "signal") == 0)
468 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000469 if (strcmp(s, "desc") == 0)
470 return TRACE_DESC;
Namhyung Kim96792962012-10-24 11:41:57 +0900471 if (strcmp(s, "memory") == 0)
472 return TRACE_MEMORY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000473 return -1;
474}
475
476void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000477qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000478{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000479 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000480 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000481 char *copy;
482 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000483 int i, n;
484
485 opt = &qual_options[0];
486 for (i = 0; (p = qual_options[i].option_name); i++) {
487 n = strlen(p);
488 if (strncmp(s, p, n) == 0 && s[n] == '=') {
489 opt = &qual_options[i];
490 s += n + 1;
491 break;
492 }
493 }
494 not = 0;
495 if (*s == '!') {
496 not = 1;
497 s++;
498 }
499 if (strcmp(s, "none") == 0) {
500 not = 1 - not;
501 s = "all";
502 }
503 if (strcmp(s, "all") == 0) {
504 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000505 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000506 }
507 return;
508 }
509 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000510 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000511 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200512 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200513 if (!copy)
514 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000515 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000516 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000517 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000518 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000519 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000520
521#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000522 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000523 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000524 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100525#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000526
527#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000528 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000529 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000530 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100531#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000532
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000533 continue;
534 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000535 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100536 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000537 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000538 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000539 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000540 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000541 return;
542}
543
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000544#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000545static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000546decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000547{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000548 unsigned long addr;
549 unsigned int i, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000550
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000551 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
552 return;
553
554 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
555 addr = tcp->u_arg[1];
556 tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100557 size = current_wordsize;
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000558 for (i = 0; i < tcp->u_nargs; ++i) {
559 if (size == sizeof(int)) {
560 unsigned int arg;
561 if (umove(tcp, addr, &arg) < 0)
562 arg = 0;
563 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000564 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000565 else {
566 unsigned long arg;
567 if (umove(tcp, addr, &arg) < 0)
568 arg = 0;
569 tcp->u_arg[i] = arg;
570 }
571 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000572 }
573}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000574#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400575
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000576#ifdef SYS_ipc_subcall
577static void
578decode_ipc_subcall(struct tcb *tcp)
579{
580 unsigned int i;
581
582 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
583 return;
584
585 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
586 tcp->u_nargs = sysent[tcp->scno].nargs;
587 for (i = 0; i < tcp->u_nargs; i++)
588 tcp->u_arg[i] = tcp->u_arg[i + 1];
589}
590#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000591
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200592int
593printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000594{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200595 if (entering(tcp)) {
596 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000597
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200598 for (i = 0; i < tcp->u_nargs; i++)
599 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
600 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000601 return 0;
602}
603
Denys Vlasenko72879c62012-02-27 14:18:02 +0100604int
605printargs_lu(struct tcb *tcp)
606{
607 if (entering(tcp)) {
608 int i;
609
610 for (i = 0; i < tcp->u_nargs; i++)
611 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
612 }
613 return 0;
614}
615
616int
617printargs_ld(struct tcb *tcp)
618{
619 if (entering(tcp)) {
620 int i;
621
622 for (i = 0; i < tcp->u_nargs; i++)
623 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
624 }
625 return 0;
626}
627
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100628#if defined(SPARC) || defined(SPARC64) || defined(IA64) || defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200629long
630getrval2(struct tcb *tcp)
631{
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100632 long val;
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200633
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100634# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200635 val = regs.u_regs[U_REG_O1];
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100636# elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200637 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
638 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100639# elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200640 if (upeek(tcp, PT_R9, &val) < 0)
641 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100642# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200643
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200644 return val;
645}
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100646#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200647
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200648int
649is_restart_error(struct tcb *tcp)
650{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200651 switch (tcp->u_error) {
652 case ERESTARTSYS:
653 case ERESTARTNOINTR:
654 case ERESTARTNOHAND:
655 case ERESTART_RESTARTBLOCK:
656 return 1;
657 default:
658 break;
659 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200660 return 0;
661}
662
Denys Vlasenko523635f2012-02-25 02:44:25 +0100663#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100664struct pt_regs i386_regs;
H.J. Lu35be5812012-04-16 13:00:01 +0200665#elif defined(X86_64) || defined(X32)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100666/*
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100667 * On i386, pt_regs and user_regs_struct are the same,
668 * but on 64 bit x86, user_regs_struct has six more fields:
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100669 * fs_base, gs_base, ds, es, fs, gs.
670 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
671 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100672struct i386_user_regs_struct {
673 uint32_t ebx;
674 uint32_t ecx;
675 uint32_t edx;
676 uint32_t esi;
677 uint32_t edi;
678 uint32_t ebp;
679 uint32_t eax;
680 uint32_t xds;
681 uint32_t xes;
682 uint32_t xfs;
683 uint32_t xgs;
684 uint32_t orig_eax;
685 uint32_t eip;
686 uint32_t xcs;
687 uint32_t eflags;
688 uint32_t esp;
689 uint32_t xss;
690};
691static union {
692 struct user_regs_struct x86_64_r;
693 struct i386_user_regs_struct i386_r;
694} x86_regs_union;
695# define x86_64_regs x86_regs_union.x86_64_r
696# define i386_regs x86_regs_union.i386_r
697static struct iovec x86_io = {
698 .iov_base = &x86_regs_union
699};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100700#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200701long ia32 = 0; /* not static */
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100702static long ia64_r8, ia64_r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100703#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +0100704static long ppc_result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100705#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100706static long m68k_d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100707#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100708static long bfin_r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100709#elif defined(ARM)
Denys Vlasenko401374e2013-02-06 18:24:39 +0100710struct pt_regs arm_regs; /* not static */
Steve McIntyred8d3bd32012-10-24 17:58:16 +0100711#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100712static union {
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100713 struct user_pt_regs aarch64_r;
714 struct arm_pt_regs arm_r;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100715} arm_regs_union;
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100716# define aarch64_regs arm_regs_union.aarch64_r
717# define arm_regs arm_regs_union.arm_r
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100718static struct iovec aarch64_io = {
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100719 .iov_base = &arm_regs_union
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100720};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100721#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100722static long alpha_r0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100723static long alpha_a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100724#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200725static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100726#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100727struct pt_regs regs; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100728#elif defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100729static long long mips_a3;
730static long long mips_r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100731#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100732static long mips_a3;
733static long mips_r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100734#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200735static long gpr2;
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200736static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100737#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100738static long hppa_r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100739#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100740static long sh_r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100741#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100742static long sh64_r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100743#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100744static long cris_r10;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100745#elif defined(TILE)
746struct pt_regs tile_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100747#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100748static long microblaze_r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100749#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000750
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100751void
752printcall(struct tcb *tcp)
753{
754#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
755 sizeof(long) == 8 ? "[????????????????] " : \
756 NULL /* crash */)
757 if (get_regs_error) {
758 PRINTBADPC;
759 return;
760 }
761#if defined(I386)
762 tprintf("[%08lx] ", i386_regs.eip);
763#elif defined(S390) || defined(S390X)
764 long psw;
765 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
766 PRINTBADPC;
767 return;
768 }
769# ifdef S390
770 tprintf("[%08lx] ", psw);
771# elif S390X
Dmitry V. Levinddba73e2013-02-05 19:01:58 +0000772 tprintf("[%016lx] ", psw);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100773# endif
774#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100775 if (x86_io.iov_len == sizeof(i386_regs)) {
776 tprintf("[%08x] ", (unsigned) i386_regs.eip);
777 } else {
778# if defined(X86_64)
779 tprintf("[%016lx] ", (unsigned long) x86_64_regs.rip);
780# elif defined(X32)
781 /* Note: this truncates 64-bit rip to 32 bits */
782 tprintf("[%08lx] ", (unsigned long) x86_64_regs.rip);
783# endif
784 }
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100785#elif defined(IA64)
786 long ip;
787
788 if (upeek(tcp, PT_B0, &ip) < 0) {
789 PRINTBADPC;
790 return;
791 }
792 tprintf("[%08lx] ", ip);
793#elif defined(POWERPC)
794 long pc;
795
796 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
797 PRINTBADPC;
798 return;
799 }
800# ifdef POWERPC64
801 tprintf("[%016lx] ", pc);
802# else
803 tprintf("[%08lx] ", pc);
804# endif
805#elif defined(M68K)
806 long pc;
807
808 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
809 tprints("[????????] ");
810 return;
811 }
812 tprintf("[%08lx] ", pc);
813#elif defined(ALPHA)
814 long pc;
815
816 if (upeek(tcp, REG_PC, &pc) < 0) {
817 tprints("[????????????????] ");
818 return;
819 }
820 tprintf("[%08lx] ", pc);
821#elif defined(SPARC)
822 tprintf("[%08lx] ", regs.pc);
823#elif defined(SPARC64)
824 tprintf("[%08lx] ", regs.tpc);
825#elif defined(HPPA)
826 long pc;
827
828 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
829 tprints("[????????] ");
830 return;
831 }
832 tprintf("[%08lx] ", pc);
833#elif defined(MIPS)
834 long pc;
835
836 if (upeek(tcp, REG_EPC, &pc) < 0) {
837 tprints("[????????] ");
838 return;
839 }
840 tprintf("[%08lx] ", pc);
841#elif defined(SH)
842 long pc;
843
844 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
845 tprints("[????????] ");
846 return;
847 }
848 tprintf("[%08lx] ", pc);
849#elif defined(SH64)
850 long pc;
851
852 if (upeek(tcp, REG_PC, &pc) < 0) {
853 tprints("[????????????????] ");
854 return;
855 }
856 tprintf("[%08lx] ", pc);
857#elif defined(ARM)
Denys Vlasenko401374e2013-02-06 18:24:39 +0100858 tprintf("[%08lx] ", arm_regs.ARM_pc);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100859#elif defined(AARCH64)
860 /* tprintf("[%016lx] ", aarch64_regs.regs[???]); */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100861#elif defined(AVR32)
862 tprintf("[%08lx] ", regs.pc);
863#elif defined(BFIN)
864 long pc;
865
866 if (upeek(tcp, PT_PC, &pc) < 0) {
867 PRINTBADPC;
868 return;
869 }
870 tprintf("[%08lx] ", pc);
871#elif defined(CRISV10)
872 long pc;
873
874 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
875 PRINTBADPC;
876 return;
877 }
878 tprintf("[%08lx] ", pc);
879#elif defined(CRISV32)
880 long pc;
881
882 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
883 PRINTBADPC;
884 return;
885 }
886 tprintf("[%08lx] ", pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100887#elif defined(TILE)
888# ifdef _LP64
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500889 tprintf("[%016lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100890# else
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500891 tprintf("[%08lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100892# endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100893#endif /* architecture */
894}
895
896#ifndef get_regs
897long get_regs_error;
898void get_regs(pid_t pid)
899{
900# if defined(AVR32)
901 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
902# elif defined(I386)
903 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &i386_regs);
904# elif defined(X86_64) || defined(X32)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100905 /* PTRACE_GETREGSET was introduced around 2.6.25 */
906 if (os_release >= KERNEL_VERSION(2,6,30)) {
907 /*x86_io.iov_base = &x86_regs_union; - already is */
908 x86_io.iov_len = sizeof(x86_regs_union);
909 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (long) &x86_io);
910 } else {
911 /* Use old method, with heuristical detection of 32-bitness */
912 x86_io.iov_len = sizeof(x86_64_regs);
913 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &x86_64_regs);
914 if (!get_regs_error && x86_64_regs.cs == 0x23) {
915 x86_io.iov_len = sizeof(i386_regs);
916 /*
917 * The order is important: i386_regs and x86_64_regs
918 * are overlaid in memory!
919 */
920 i386_regs.ebx = x86_64_regs.rbx;
921 i386_regs.ecx = x86_64_regs.rcx;
922 i386_regs.edx = x86_64_regs.rdx;
923 i386_regs.esi = x86_64_regs.rsi;
924 i386_regs.edi = x86_64_regs.rdi;
925 i386_regs.ebp = x86_64_regs.rbp;
926 i386_regs.eax = x86_64_regs.rax;
927 /*i386_regs.xds = x86_64_regs.ds; unused by strace */
928 /*i386_regs.xes = x86_64_regs.es; ditto... */
929 /*i386_regs.xfs = x86_64_regs.fs;*/
930 /*i386_regs.xgs = x86_64_regs.gs;*/
931 i386_regs.orig_eax = x86_64_regs.orig_rax;
932 i386_regs.eip = x86_64_regs.rip;
933 /*i386_regs.xcs = x86_64_regs.cs;*/
934 /*i386_regs.eflags = x86_64_regs.eflags;*/
935 i386_regs.esp = x86_64_regs.rsp;
936 /*i386_regs.xss = x86_64_regs.ss;*/
937 }
938 }
Denys Vlasenko401374e2013-02-06 18:24:39 +0100939# elif defined(ARM)
940 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (void *)&arm_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100941# elif defined(AARCH64)
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100942 /*aarch64_io.iov_base = &arm_regs_union; - already is */
943 aarch64_io.iov_len = sizeof(arm_regs_union);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100944 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void *)&aarch64_io);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100945# if 0
946 /* Paranoia checks */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100947 if (get_regs_error)
948 return;
949 switch (aarch64_io.iov_len) {
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100950 case sizeof(aarch64_regs):
951 /* We are in 64-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100952 break;
953 case sizeof(arm_regs):
954 /* We are in 32-bit mode */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100955 break;
956 default:
957 get_regs_error = -1;
958 break;
959 }
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100960# endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100961# elif defined(SPARC) || defined(SPARC64)
962 get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&regs, 0);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100963# elif defined(TILE)
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500964 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &tile_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100965# endif
966}
967#endif
968
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200969/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100970 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
971 * 1: ok, continue in trace_syscall_entering().
972 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200973 * ("????" etc) and bail out.
974 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100975static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200976get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000977{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000978 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000979
Denys Vlasenko523635f2012-02-25 02:44:25 +0100980#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000981 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200982 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000983
984 if (syscall_mode != -ENOSYS) {
985 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000986 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000987 */
988 scno = syscall_mode;
989 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000990 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000991 * Old style of "passing" the scno via the SVC instruction.
992 */
Denys Vlasenko7ba8e722013-02-08 15:50:05 +0100993 long psw;
Michal Ludvig882eda82002-11-11 12:50:47 +0000994 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200995 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200996 static const int gpr_offset[16] = {
997 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
998 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
999 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
1000 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
1001 };
Roland McGrath761b5d72002-12-15 23:58:31 +00001002
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001003 if (upeek(tcp, PT_PSWADDR, &psw) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +00001004 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +00001005 errno = 0;
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001006 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(psw - sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +00001007 if (errno) {
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001008 perror_msg("%s", "peektext(psw-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +00001009 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +00001010 }
Michal Ludvig882eda82002-11-11 12:50:47 +00001011
1012 /*
1013 * We have to check if the SVC got executed directly or via an
1014 * EXECUTE instruction. In case of EXECUTE it is necessary to do
1015 * instruction decoding to derive the system call number.
1016 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
1017 * so that this doesn't work if a SVC opcode is part of an EXECUTE
1018 * opcode. Since there is no way to find out the opcode size this
1019 * is the best we can do...
1020 */
Michal Ludvig882eda82002-11-11 12:50:47 +00001021 if ((opcode & 0xff00) == 0x0a00) {
1022 /* SVC opcode */
1023 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +00001024 }
Michal Ludvig882eda82002-11-11 12:50:47 +00001025 else {
1026 /* SVC got executed by EXECUTE instruction */
1027
1028 /*
1029 * Do instruction decoding of EXECUTE. If you really want to
1030 * understand this, read the Principles of Operations.
1031 */
1032 svc_addr = (void *) (opcode & 0xfff);
1033
1034 tmp = 0;
1035 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001036 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001037 return -1;
1038 svc_addr += tmp;
1039
1040 tmp = 0;
1041 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001042 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001043 return -1;
1044 svc_addr += tmp;
1045
Denys Vlasenkofb036672009-01-23 16:30:26 +00001046 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +00001047 if (errno)
1048 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001049# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +00001050 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001051# else
Michal Ludvig882eda82002-11-11 12:50:47 +00001052 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001053# endif
Michal Ludvig882eda82002-11-11 12:50:47 +00001054 tmp = 0;
1055 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001056 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001057 return -1;
1058
1059 scno = (scno | tmp) & 0xff;
1060 }
1061 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001062#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001063 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001064 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001065# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001066 /* TODO: speed up strace by not doing this at every syscall.
1067 * We only need to do it after execve.
1068 */
1069 int currpers;
1070 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +02001071
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001072 /* Check for 64/32 bit mode. */
1073 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
1074 return -1;
1075 /* SF is bit 0 of MSR */
1076 if (val < 0)
1077 currpers = 0;
1078 else
1079 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001080 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001081# endif
1082#elif defined(AVR32)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001083 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001084#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001085 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001086 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001087#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001088 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +02001089#elif defined(X86_64) || defined(X32)
1090# ifndef __X32_SYSCALL_BIT
1091# define __X32_SYSCALL_BIT 0x40000000
1092# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001093 int currpers;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001094# if 1
1095 /* GETREGSET of NT_PRSTATUS tells us regset size,
1096 * which unambiguously detects i386.
1097 *
1098 * Linux kernel distinguishes x86-64 and x32 processes
1099 * solely by looking at __X32_SYSCALL_BIT:
1100 * arch/x86/include/asm/compat.h::is_x32_task():
1101 * if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)
1102 * return true;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001103 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001104 if (x86_io.iov_len == sizeof(i386_regs)) {
1105 scno = i386_regs.orig_eax;
1106 currpers = 1;
1107 } else {
1108 scno = x86_64_regs.orig_rax;
1109 currpers = 0;
1110 if (scno & __X32_SYSCALL_BIT) {
1111 scno -= __X32_SYSCALL_BIT;
1112 currpers = 2;
1113 }
1114 }
1115# elif 0
1116 /* cs = 0x33 for long mode (native 64 bit and x32)
1117 * cs = 0x23 for compatibility mode (32 bit)
1118 * ds = 0x2b for x32 mode (x86-64 in 32 bit)
1119 */
1120 scno = x86_64_regs.orig_rax;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001121 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001122 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +02001123 case 0x33:
1124 if (x86_64_regs.ds == 0x2b) {
1125 currpers = 2;
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001126 scno &= ~__X32_SYSCALL_BIT;
H.J. Lu35be5812012-04-16 13:00:01 +02001127 } else
1128 currpers = 0;
1129 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001130 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001131 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001132 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001133 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001134 currpers = current_personality;
1135 break;
1136 }
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001137# elif 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001138 /* This version analyzes the opcode of a syscall instruction.
1139 * (int 0x80 on i386 vs. syscall on x86-64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001140 * It works, but is too complicated, and strictly speaking, unreliable.
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001141 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001142 unsigned long call, rip = x86_64_regs.rip;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001143 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
1144 rip -= 2;
1145 errno = 0;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001146 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001147 if (errno)
1148 fprintf(stderr, "ptrace_peektext failed: %s\n",
1149 strerror(errno));
1150 switch (call & 0xffff) {
1151 /* x86-64: syscall = 0x0f 0x05 */
1152 case 0x050f: currpers = 0; break;
1153 /* i386: int 0x80 = 0xcd 0x80 */
1154 case 0x80cd: currpers = 1; break;
1155 default:
1156 currpers = current_personality;
1157 fprintf(stderr,
1158 "Unknown syscall opcode (0x%04X) while "
1159 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001160 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001161 break;
1162 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001163# endif
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001164
H.J. Lu35be5812012-04-16 13:00:01 +02001165# ifdef X32
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001166 /* If we are built for a x32 system, then personality 0 is x32
1167 * (not x86_64), and stracing of x86_64 apps is not supported.
1168 * Stracing of i386 apps is still supported.
H.J. Lu085e4282012-04-17 11:05:04 -07001169 */
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001170 if (currpers == 0) {
1171 fprintf(stderr, "syscall_%lu(...) in unsupported "
1172 "64-bit mode of process PID=%d\n",
1173 scno, tcp->pid);
1174 return 0;
H.J. Lu35be5812012-04-16 13:00:01 +02001175 }
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001176 currpers &= ~2; /* map 2,1 to 0,1 */
H.J. Lu35be5812012-04-16 13:00:01 +02001177# endif
H.J. Lu085e4282012-04-17 11:05:04 -07001178 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001179#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001180# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001181 long psr;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001182 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001183 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001184 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001185 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001186 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001187 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001188 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001189 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001190 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001191#elif defined(AARCH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001192 switch (aarch64_io.iov_len) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001193 case sizeof(aarch64_regs):
1194 /* We are in 64-bit mode */
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001195 scno = aarch64_regs.regs[8];
1196 update_personality(tcp, 1);
1197 break;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001198 case sizeof(arm_regs):
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001199 /* We are in 32-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001200 scno = arm_regs.ARM_r7;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001201 update_personality(tcp, 0);
1202 break;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001203 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001204#elif defined(ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001205 /*
1206 * We only need to grab the syscall number on syscall entry.
1207 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001208 if (arm_regs.ARM_ip == 0) {
Roland McGrath0f87c492003-06-03 23:29:04 +00001209 /*
Denys Vlasenko401374e2013-02-06 18:24:39 +01001210 * Note: we only deal with 32-bit CPUs here
Roland McGrath0f87c492003-06-03 23:29:04 +00001211 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001212 if (arm_regs.ARM_cpsr & 0x20) {
Roland McGrath0f87c492003-06-03 23:29:04 +00001213 /*
1214 * Get the Thumb-mode system call number
1215 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001216 scno = arm_regs.ARM_r7;
Roland McGrath0f87c492003-06-03 23:29:04 +00001217 } else {
1218 /*
1219 * Get the ARM-mode system call number
1220 */
1221 errno = 0;
Denys Vlasenko401374e2013-02-06 18:24:39 +01001222 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(arm_regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +00001223 if (errno)
1224 return -1;
1225
Roland McGrathf691bd22006-04-25 07:34:41 +00001226 /* Handle the EABI syscall convention. We do not
1227 bother converting structures between the two
1228 ABIs, but basic functionality should work even
1229 if strace and the traced program have different
1230 ABIs. */
1231 if (scno == 0xef000000) {
Denys Vlasenko401374e2013-02-06 18:24:39 +01001232 scno = arm_regs.ARM_r7;
Roland McGrathf691bd22006-04-25 07:34:41 +00001233 } else {
1234 if ((scno & 0x0ff00000) != 0x0f900000) {
1235 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1236 scno);
1237 return -1;
1238 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001239
Roland McGrathf691bd22006-04-25 07:34:41 +00001240 /*
1241 * Fixup the syscall number
1242 */
1243 scno &= 0x000fffff;
1244 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001245 }
Roland McGrath56703312008-05-20 01:35:55 +00001246 if (scno & 0x0f0000) {
1247 /*
1248 * Handle ARM specific syscall
1249 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001250 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +00001251 scno &= 0x0000ffff;
1252 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001253 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001254
Roland McGrath0f87c492003-06-03 23:29:04 +00001255 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001256 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1257 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001258 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001259#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001260 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001261 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001262#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001263 unsigned long long regs[38];
1264
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001265 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001266 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001267 mips_a3 = regs[REG_A3];
1268 mips_r2 = regs[REG_V0];
Roland McGrath542c2c62008-05-20 01:11:56 +00001269
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001270 scno = mips_r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001271 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001272 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001273 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001274 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001275 return 0;
1276 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001277 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001278#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001279 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001280 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001281 if (upeek(tcp, REG_V0, &scno) < 0)
1282 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001283
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001284 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001285 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001286 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001287 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001288 return 0;
1289 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001290 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001291#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001292 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001293 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001294 if (upeek(tcp, REG_R0, &scno) < 0)
1295 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001296
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001297 /*
1298 * Do some sanity checks to figure out if it's
1299 * really a syscall entry
1300 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001301 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001302 if (alpha_a3 == 0 || alpha_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001303 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001304 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001305 return 0;
1306 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001307 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001308#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001309 /* Disassemble the syscall trap. */
1310 /* Retrieve the syscall trap instruction. */
Denys Vlasenko46455822013-02-05 17:02:59 +01001311 unsigned long trap;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001312 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001313# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001314 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1315 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001316# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001317 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001318# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001319 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001320 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001321
1322 /* Disassemble the trap to see what personality to use. */
1323 switch (trap) {
1324 case 0x91d02010:
1325 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001326 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001327 break;
1328 case 0x91d0206d:
1329 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001330 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001331 break;
1332 case 0x91d02000:
1333 /* SunOS syscall trap. (pers 1) */
1334 fprintf(stderr, "syscall: SunOS no support\n");
1335 return -1;
1336 case 0x91d02008:
1337 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001338 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001339 break;
1340 case 0x91d02009:
1341 /* NetBSD/FreeBSD syscall trap. */
1342 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1343 return -1;
1344 case 0x91d02027:
1345 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001346 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001347 break;
1348 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001349# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001350 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001351# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001352 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001353# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001354 return -1;
1355 }
1356
1357 /* Extract the system call number from the registers. */
1358 if (trap == 0x91d02027)
1359 scno = 156;
1360 else
1361 scno = regs.u_regs[U_REG_G1];
1362 if (scno == 0) {
1363 scno = regs.u_regs[U_REG_O0];
1364 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1365 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001366#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001367 if (upeek(tcp, PT_GR20, &scno) < 0)
1368 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001369#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001370 /*
1371 * In the new syscall ABI, the system call number is in R3.
1372 */
1373 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1374 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001375
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001376 if (scno < 0) {
1377 /* Odd as it may seem, a glibc bug has been known to cause
1378 glibc to issue bogus negative syscall numbers. So for
1379 our purposes, make strace print what it *should* have been */
1380 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001381 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001382 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001383 "Detected glibc bug: bogus system call"
1384 " number = %ld, correcting to %ld\n",
1385 scno,
1386 correct_scno);
1387 scno = correct_scno;
1388 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001389#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001390 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001391 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001392 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001393#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001394 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1395 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001396#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001397 int currpers;
1398 scno = tile_regs.regs[10];
1399# ifdef __tilepro__
1400 currpers = 1;
1401# else
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001402# ifndef PT_FLAGS_COMPAT
1403# define PT_FLAGS_COMPAT 0x10000 /* from Linux 3.8 on */
1404# endif
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001405 if (tile_regs.flags & PT_FLAGS_COMPAT)
1406 currpers = 1;
1407 else
1408 currpers = 0;
1409# endif
1410 update_personality(tcp, currpers);
1411
1412 if (!(tcp->flags & TCB_INSYSCALL)) {
1413 /* Check if we return from execve. */
1414 if (tcp->flags & TCB_WAITEXECVE) {
1415 tcp->flags &= ~TCB_WAITEXECVE;
1416 return 0;
1417 }
1418 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001419#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001420 if (upeek(tcp, 0, &scno) < 0)
1421 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001422#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001423
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001424 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001425 return 1;
1426}
1427
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001428/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001429 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001430 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1431 * 1: ok, continue in trace_syscall_entering().
1432 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001433 * ("????" etc) and bail out.
1434 */
Roland McGratha4d48532005-06-08 20:45:28 +00001435static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001436syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001437{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001438 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001439#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001440 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001441 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001442 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1443 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001444 }
H.J. Lu35be5812012-04-16 13:00:01 +02001445#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001446 {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001447 long rax;
1448 if (x86_io.iov_len == sizeof(i386_regs)) {
1449 /* Sign extend from 32 bits */
1450 rax = (int32_t)i386_regs.eax;
1451 } else {
1452 /* Note: in X32 build, this truncates 64 to 32 bits */
1453 rax = x86_64_regs.rax;
1454 }
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001455 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001456 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001457 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1458 return 0;
1459 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001460 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001461#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001462 /* TODO: we already fetched PT_GPR2 in get_scno
1463 * and stored it in syscall_mode, reuse it here
1464 * instead of re-fetching?
1465 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001466 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001467 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001468 if (syscall_mode != -ENOSYS)
1469 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001470 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001471 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001472 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001473 return 0;
1474 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001475#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001476 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001477 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001478 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001479 if (m68k_d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001480 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001481 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", m68k_d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001482 return 0;
1483 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001484#elif defined(IA64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001485 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001486 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001487 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001488 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001489 if (ia32 && ia64_r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001490 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001491 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", ia64_r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001492 return 0;
1493 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001494#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001495 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001496 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001497 if (cris_r10 != -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 (r10 = %ld)\n", cris_r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001500 return 0;
1501 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001502#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001503 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001504 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001505 if (microblaze_r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001506 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001507 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", microblaze_r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001508 return 0;
1509 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001510#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001511 return 1;
1512}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001513
Denys Vlasenko146b9442012-03-18 22:10:48 +01001514static void
1515internal_fork(struct tcb *tcp)
1516{
1517#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1518# define ARG_FLAGS 1
1519#else
1520# define ARG_FLAGS 0
1521#endif
1522#ifndef CLONE_UNTRACED
1523# define CLONE_UNTRACED 0x00800000
1524#endif
1525 if ((ptrace_setoptions
1526 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1527 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1528 return;
1529
1530 if (!followfork)
1531 return;
1532
1533 if (entering(tcp)) {
1534 /*
1535 * We won't see the new child if clone is called with
1536 * CLONE_UNTRACED, so we keep the same logic with that option
1537 * and don't trace it.
1538 */
1539 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1540 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1541 return;
1542 setbpt(tcp);
1543 } else {
1544 if (tcp->flags & TCB_BPTSET)
1545 clearbpt(tcp);
1546 }
1547}
1548
1549#if defined(TCB_WAITEXECVE)
1550static void
1551internal_exec(struct tcb *tcp)
1552{
1553 /* Maybe we have post-execve SIGTRAP suppressed? */
1554 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1555 return; /* yes, no need to do anything */
1556
1557 if (exiting(tcp) && syserror(tcp))
1558 /* Error in execve, no post-execve SIGTRAP expected */
1559 tcp->flags &= ~TCB_WAITEXECVE;
1560 else
1561 tcp->flags |= TCB_WAITEXECVE;
1562}
1563#endif
1564
1565static void
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001566syscall_fixup_for_fork_exec(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001567{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001568 /*
1569 * We must always trace a few critical system calls in order to
1570 * correctly support following forks in the presence of tracing
1571 * qualifiers.
1572 */
1573 int (*func)();
1574
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001575 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001576 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001577
1578 func = sysent[tcp->scno].sys_func;
1579
1580 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001581 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001582 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001583 ) {
1584 internal_fork(tcp);
1585 return;
1586 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001587
Denys Vlasenko84703742012-02-25 02:38:52 +01001588#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001589 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001590# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001591 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001592# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001593 ) {
1594 internal_exec(tcp);
1595 return;
1596 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001597#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001598}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001599
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001600/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001601static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001602get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001603{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001604 int i, nargs;
1605
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001606 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001607 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001608 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001609 nargs = tcp->u_nargs = MAX_ARGS;
1610
Denys Vlasenko523635f2012-02-25 02:44:25 +01001611#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001612 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001613 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1614 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001615#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001616 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001617 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1618 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001619#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001620 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001621 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001622 long rbs_end;
1623 /* be backwards compatible with kernel < 2.4.4... */
1624# ifndef PT_RBS_END
1625# define PT_RBS_END PT_AR_BSP
1626# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001627
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001628 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1629 return -1;
1630 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001631 return -1;
1632
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001633 sof = (cfm >> 0) & 0x7f;
1634 sol = (cfm >> 7) & 0x7f;
1635 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1636
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001637 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001638 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1639 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1640 return -1;
1641 }
1642 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001643 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1644 PT_R9 /* ECX = out1 */,
1645 PT_R10 /* EDX = out2 */,
1646 PT_R14 /* ESI = out3 */,
1647 PT_R15 /* EDI = out4 */,
1648 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001649
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001650 for (i = 0; i < nargs; ++i) {
1651 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1652 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001653 /* truncate away IVE sign-extension */
1654 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001655 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001656 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001657#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001658 /* N32 and N64 both use up to six registers. */
1659 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001660
1661 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1662 return -1;
1663
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001664 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001665 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001666# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001667 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001668# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001669 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001670#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001671 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001672 long sp;
1673
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001674 if (upeek(tcp, REG_SP, &sp) < 0)
1675 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001676 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001677 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1678 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001679 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001680 (char *)(tcp->u_arg + 4));
1681 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001682 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001683 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001684 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001685 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001686#elif defined(POWERPC)
1687# ifndef PT_ORIG_R3
1688# define PT_ORIG_R3 34
1689# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001690 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001691 if (upeek(tcp, (i==0) ?
1692 (sizeof(unsigned long) * PT_ORIG_R3) :
1693 ((i+PT_R3) * sizeof(unsigned long)),
1694 &tcp->u_arg[i]) < 0)
1695 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001696 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001697#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001698 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001699 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001700#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001701 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001702 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1703 return -1;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001704#elif defined(ARM) || defined(AARCH64)
1705# if defined(AARCH64)
1706 if (tcp->currpers == 1)
1707 for (i = 0; i < nargs; ++i)
1708 tcp->u_arg[i] = aarch64_regs.regs[i];
1709 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001710# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001711 for (i = 0; i < nargs; ++i)
Denys Vlasenko401374e2013-02-06 18:24:39 +01001712 tcp->u_arg[i] = arm_regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001713#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001714 (void)i;
1715 (void)nargs;
1716 tcp->u_arg[0] = regs.r12;
1717 tcp->u_arg[1] = regs.r11;
1718 tcp->u_arg[2] = regs.r10;
1719 tcp->u_arg[3] = regs.r9;
1720 tcp->u_arg[4] = regs.r5;
1721 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001722#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001723 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 +02001724
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001725 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001726 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1727 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001728#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001729 static const int syscall_regs[MAX_ARGS] = {
1730 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1731 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001732 };
1733
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001734 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001735 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001736 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001737#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001738 int i;
1739 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001740 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001741
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001742 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001743 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1744 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001745#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001746 (void)i;
1747 (void)nargs;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001748 if (x86_io.iov_len != sizeof(i386_regs)) {
1749 /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001750 tcp->u_arg[0] = x86_64_regs.rdi;
1751 tcp->u_arg[1] = x86_64_regs.rsi;
1752 tcp->u_arg[2] = x86_64_regs.rdx;
1753 tcp->u_arg[3] = x86_64_regs.r10;
1754 tcp->u_arg[4] = x86_64_regs.r8;
1755 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001756# ifdef X32
1757 tcp->ext_arg[0] = x86_64_regs.rdi;
1758 tcp->ext_arg[1] = x86_64_regs.rsi;
1759 tcp->ext_arg[2] = x86_64_regs.rdx;
1760 tcp->ext_arg[3] = x86_64_regs.r10;
1761 tcp->ext_arg[4] = x86_64_regs.r8;
1762 tcp->ext_arg[5] = x86_64_regs.r9;
1763# endif
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001764 } else {
1765 /* i386 ABI */
1766 /* Sign-extend from 32 bits */
1767 tcp->u_arg[0] = (long)(int32_t)i386_regs.ebx;
1768 tcp->u_arg[1] = (long)(int32_t)i386_regs.ecx;
1769 tcp->u_arg[2] = (long)(int32_t)i386_regs.edx;
1770 tcp->u_arg[3] = (long)(int32_t)i386_regs.esi;
1771 tcp->u_arg[4] = (long)(int32_t)i386_regs.edi;
1772 tcp->u_arg[5] = (long)(int32_t)i386_regs.ebp;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001773 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001774#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001775 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001776 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1777 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001778#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001779 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001780 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001781 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001782 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001783
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001784 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001785 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1786 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001787#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001788 for (i = 0; i < nargs; ++i)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001789 tcp->u_arg[i] = tile_regs.regs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001790#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001791 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001792 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1793 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001794#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001795 (void)i;
1796 (void)nargs;
1797 tcp->u_arg[0] = i386_regs.ebx;
1798 tcp->u_arg[1] = i386_regs.ecx;
1799 tcp->u_arg[2] = i386_regs.edx;
1800 tcp->u_arg[3] = i386_regs.esi;
1801 tcp->u_arg[4] = i386_regs.edi;
1802 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001803#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001804 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001805 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1806 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001807#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001808 return 1;
1809}
1810
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001811static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001812trace_syscall_entering(struct tcb *tcp)
1813{
1814 int res, scno_good;
1815
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001816#if defined TCB_WAITEXECVE
1817 if (tcp->flags & TCB_WAITEXECVE) {
1818 /* This is the post-execve SIGTRAP. */
1819 tcp->flags &= ~TCB_WAITEXECVE;
1820 return 0;
1821 }
1822#endif
1823
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001824 scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001825 if (res == 0)
1826 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001827 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001828 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001829 if (res == 0)
1830 return res;
1831 if (res == 1)
1832 res = get_syscall_args(tcp);
1833 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001834
1835 if (res != 1) {
1836 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001837 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001838 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001839 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001840 tprintf("syscall_%lu(", tcp->scno);
1841 else
1842 tprintf("%s(", sysent[tcp->scno].sys_name);
1843 /*
1844 * " <unavailable>" will be added later by the code which
1845 * detects ptrace errors.
1846 */
1847 goto ret;
1848 }
1849
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001850#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1851 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001852# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001853 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001854 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001855 break;
1856 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001857# endif
1858# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001859 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001860 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001861 break;
1862 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001863# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001864 break;
1865 }
1866#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1867
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001868 if (need_fork_exec_workarounds)
1869 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001870
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001871 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001872 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1873 (tracing_paths && !pathtrace_match(tcp))) {
1874 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1875 return 0;
1876 }
1877
1878 tcp->flags &= ~TCB_FILTERED;
1879
1880 if (cflag == CFLAG_ONLY_STATS) {
1881 res = 0;
1882 goto ret;
1883 }
1884
1885 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001886 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001887 tprintf("syscall_%lu(", tcp->scno);
1888 else
1889 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001890 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001891 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1892 sysent[tcp->scno].sys_func != sys_exit))
1893 res = printargs(tcp);
1894 else
1895 res = (*sysent[tcp->scno].sys_func)(tcp);
1896
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001897 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001898 ret:
1899 tcp->flags |= TCB_INSYSCALL;
1900 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001901 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001902 gettimeofday(&tcp->etime, NULL);
1903 return res;
1904}
1905
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001906/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001907 * 1: ok, continue in trace_syscall_exiting().
1908 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001909 * ("????" etc) and bail out.
1910 */
1911static int
1912get_syscall_result(struct tcb *tcp)
1913{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001914#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001915 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1916 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001917#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001918# define SO_MASK 0x10000000
1919 {
1920 long flags;
1921 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1922 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001923 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001924 return -1;
1925 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001926 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001927 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001928#elif defined(AVR32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001929 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001930#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001931 if (upeek(tcp, PT_R0, &bfin_r0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001932 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001933#elif defined(I386)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001934 /* already done by get_regs */
H.J. Lu35be5812012-04-16 13:00:01 +02001935#elif defined(X86_64) || defined(X32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001936 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001937#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001938# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001939 long psr;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001940 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1941 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001942 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001943 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001944 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001945 return -1;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001946#elif defined(ARM)
1947 /* already done by get_regs */
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001948#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001949 /* register reading already done by get_regs */
1950
1951 /* Used to do this, but we did it on syscall entry already: */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001952 /* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
1953 * else it's personality 0.
1954 */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001955 /*update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));*/
Denys Vlasenko523635f2012-02-25 02:44:25 +01001956#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001957 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001958 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001959#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001960 unsigned long long regs[38];
1961
1962 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1963 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001964 mips_a3 = regs[REG_A3];
1965 mips_r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001966#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001967 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001968 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001969 if (upeek(tcp, REG_V0, &mips_r2) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001970 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001971#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001972 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001973 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001974 if (upeek(tcp, REG_R0, &alpha_r0) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001975 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001976#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001977 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001978#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001979 if (upeek(tcp, PT_GR28, &hppa_r28) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001980 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001981#elif defined(SH)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001982 /* new syscall ABI returns result in R0 */
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001983 if (upeek(tcp, 4*REG_REG0, (long *)&sh_r0) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001984 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001985#elif defined(SH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001986 /* ABI defines result returned in r9 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001987 if (upeek(tcp, REG_GENERAL(9), (long *)&sh64_r9) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001988 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001989#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001990 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001991 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001992#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001993 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001994#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001995 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001996 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001997#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001998 return 1;
1999}
2000
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002001/* Called at each syscall exit */
2002static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002003syscall_fixup_on_sysexit(struct tcb *tcp)
2004{
Denys Vlasenko523635f2012-02-25 02:44:25 +01002005#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002006 if (syscall_mode != -ENOSYS)
2007 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02002008 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002009 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
2010 /*
2011 * Return from execve.
2012 * Fake a return value of zero. We leave the TCB_WAITEXECVE
2013 * flag set for the post-execve SIGTRAP to see and reset.
2014 */
2015 gpr2 = 0;
2016 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002017#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002018}
2019
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002020/*
2021 * Check the syscall return value register value for whether it is
2022 * a negated errno code indicating an error, or a success return value.
2023 */
2024static inline int
2025is_negated_errno(unsigned long int val)
2026{
2027 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002028#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01002029 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002030 val = (unsigned int) val;
2031 max = (unsigned int) max;
2032 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002033#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002034 return val > max;
2035}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002036
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002037#if defined(X32)
2038static inline int
2039is_negated_errno_x32(unsigned long long val)
2040{
2041 unsigned long long max = -(long long) nerrnos;
2042 /*
2043 * current_wordsize is 4 even in personality 0 (native X32)
2044 * but truncation _must not_ be done in it.
2045 * can't check current_wordsize here!
2046 */
2047 if (current_personality != 0) {
2048 val = (uint32_t) val;
2049 max = (uint32_t) max;
2050 }
2051 return val > max;
2052}
2053#endif
2054
Denys Vlasenko907735a2012-03-21 00:23:16 +01002055/* Returns:
2056 * 1: ok, continue in trace_syscall_exiting().
2057 * -1: error, trace_syscall_exiting() should print error indicator
2058 * ("????" etc) and bail out.
2059 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002060static int
2061get_error(struct tcb *tcp)
2062{
2063 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002064 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002065 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002066 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
2067 check_errno = 0;
2068 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002069#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002070 if (check_errno && is_negated_errno(gpr2)) {
2071 tcp->u_rval = -1;
2072 u_error = -gpr2;
2073 }
2074 else {
2075 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002076 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002077#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002078 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002079 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002080 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002081 }
2082 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002083 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002084 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002085#elif defined(X86_64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002086 long rax;
2087 if (x86_io.iov_len == sizeof(i386_regs)) {
2088 /* Sign extend from 32 bits */
2089 rax = (int32_t)i386_regs.eax;
2090 } else {
2091 rax = x86_64_regs.rax;
2092 }
2093 if (check_errno && is_negated_errno(rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002094 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002095 u_error = -rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002096 }
2097 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002098 tcp->u_rval = rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002099 }
2100#elif defined(X32)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002101 /* In X32, return value is 64-bit (llseek uses one).
2102 * Using merely "long rax" would not work.
2103 */
2104 long long rax;
2105 if (x86_io.iov_len == sizeof(i386_regs)) {
2106 /* Sign extend from 32 bits */
2107 rax = (int32_t)i386_regs.eax;
2108 } else {
2109 rax = x86_64_regs.rax;
2110 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002111 /* Careful: is_negated_errno() works only on longs */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002112 if (check_errno && is_negated_errno_x32(rax)) {
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002113 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002114 u_error = -rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002115 }
2116 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002117 tcp->u_rval = rax; /* truncating */
2118 tcp->u_lrval = rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002119 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002120#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002121 if (ia32) {
2122 int err;
2123
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002124 err = (int)ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002125 if (check_errno && is_negated_errno(err)) {
2126 tcp->u_rval = -1;
2127 u_error = -err;
2128 }
2129 else {
2130 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002131 }
2132 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002133 if (check_errno && ia64_r10) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002134 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002135 u_error = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002136 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002137 tcp->u_rval = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002138 }
2139 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002140#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002141 if (check_errno && mips_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002142 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002143 u_error = mips_r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002144 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002145 tcp->u_rval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002146# if defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002147 tcp->u_lrval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002148# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002149 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002150#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002151 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002152 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002153 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002154 }
2155 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002156 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002157 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002158#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002159 if (check_errno && is_negated_errno(m68k_d0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002160 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002161 u_error = -m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002162 }
2163 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002164 tcp->u_rval = m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002165 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002166#elif defined(ARM) || defined(AARCH64)
2167# if defined(AARCH64)
2168 if (tcp->currpers == 1) {
2169 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2170 tcp->u_rval = -1;
2171 u_error = -aarch64_regs.regs[0];
2172 }
2173 else {
2174 tcp->u_rval = aarch64_regs.regs[0];
2175 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002176 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002177 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01002178# endif
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002179 {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002180 if (check_errno && is_negated_errno(arm_regs.ARM_r0)) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002181 tcp->u_rval = -1;
Denys Vlasenko401374e2013-02-06 18:24:39 +01002182 u_error = -arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002183 }
2184 else {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002185 tcp->u_rval = arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002186 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002187 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002188#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002189 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
2190 tcp->u_rval = -1;
2191 u_error = -regs.r12;
2192 }
2193 else {
2194 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002195 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002196#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002197 if (check_errno && is_negated_errno(bfin_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002198 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002199 u_error = -bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002200 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002201 tcp->u_rval = bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002202 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002203#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002204 if (check_errno && alpha_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002205 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002206 u_error = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002207 }
2208 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002209 tcp->u_rval = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002210 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002211#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002212 if (check_errno && regs.psr & PSR_C) {
2213 tcp->u_rval = -1;
2214 u_error = regs.u_regs[U_REG_O0];
2215 }
2216 else {
2217 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002218 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002219#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002220 if (check_errno && regs.tstate & 0x1100000000UL) {
2221 tcp->u_rval = -1;
2222 u_error = regs.u_regs[U_REG_O0];
2223 }
2224 else {
2225 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002226 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002227#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002228 if (check_errno && is_negated_errno(hppa_r28)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002229 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002230 u_error = -hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002231 }
2232 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002233 tcp->u_rval = hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002234 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002235#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002236 if (check_errno && is_negated_errno(sh_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002237 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002238 u_error = -sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002239 }
2240 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002241 tcp->u_rval = sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002242 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002243#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002244 if (check_errno && is_negated_errno(sh64_r9)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002245 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002246 u_error = -sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002247 }
2248 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002249 tcp->u_rval = sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002250 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002251#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002252 if (check_errno && cris_r10 && (unsigned) -cris_r10 < nerrnos) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002253 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002254 u_error = -cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002255 }
2256 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002257 tcp->u_rval = cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002258 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002259#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002260 /*
2261 * The standard tile calling convention returns the value (or negative
2262 * errno) in r0, and zero (or positive errno) in r1.
2263 * Until at least kernel 3.8, however, the r1 value is not reflected
2264 * in ptregs at this point, so we use r0 here.
2265 */
2266 if (check_errno && is_negated_errno(tile_regs.regs[0])) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002267 tcp->u_rval = -1;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002268 u_error = -tile_regs.regs[0];
2269 } else {
2270 tcp->u_rval = tile_regs.regs[0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002271 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002272#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002273 if (check_errno && is_negated_errno(microblaze_r3)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002274 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002275 u_error = -microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002276 }
2277 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002278 tcp->u_rval = microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002279 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002280#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002281 tcp->u_error = u_error;
2282 return 1;
2283}
2284
2285static void
2286dumpio(struct tcb *tcp)
2287{
2288 if (syserror(tcp))
2289 return;
2290 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
2291 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002292 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002293 return;
2294 if (sysent[tcp->scno].sys_func == printargs)
2295 return;
2296 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
2297 if (sysent[tcp->scno].sys_func == sys_read ||
2298 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002299 sysent[tcp->scno].sys_func == sys_recv ||
2300 sysent[tcp->scno].sys_func == sys_recvfrom)
2301 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
2302 else if (sysent[tcp->scno].sys_func == sys_readv)
2303 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2304 return;
2305 }
2306 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
2307 if (sysent[tcp->scno].sys_func == sys_write ||
2308 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002309 sysent[tcp->scno].sys_func == sys_send ||
2310 sysent[tcp->scno].sys_func == sys_sendto)
2311 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
2312 else if (sysent[tcp->scno].sys_func == sys_writev)
2313 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2314 return;
2315 }
2316}
2317
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002318static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002319trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002320{
2321 int sys_res;
2322 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002323 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002324 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002325
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002326 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002327 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002328 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002329
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002330#if SUPPORTED_PERSONALITIES > 1
2331 update_personality(tcp, tcp->currpers);
2332#endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002333 res = (get_regs_error ? -1 : get_syscall_result(tcp));
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002334 if (res == 1) {
2335 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01002336 res = get_error(tcp); /* returns 1 or -1 */
2337 if (res == 1) {
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01002338 if (need_fork_exec_workarounds)
2339 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01002340 if (filtered(tcp)) {
2341 goto ret;
2342 }
2343 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002344 }
2345
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002346 if (cflag) {
2347 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002348 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002349 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002350 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002351 }
2352 }
2353
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002354 /* If not in -ff mode, and printing_tcp != tcp,
2355 * then the log currently does not end with output
2356 * of _our syscall entry_, but with something else.
2357 * We need to say which syscall's return is this.
2358 *
2359 * Forced reprinting via TCB_REPRINT is used only by
2360 * "strace -ff -oLOG test/threaded_execve" corner case.
2361 * It's the only case when -ff mode needs reprinting.
2362 */
2363 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2364 tcp->flags &= ~TCB_REPRINT;
2365 printleader(tcp);
2366 if (!SCNO_IN_RANGE(tcp->scno))
2367 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2368 else
2369 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2370 }
2371 printing_tcp = tcp;
2372
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002373 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002374 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002375 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002376 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002377 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002378 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002379 tcp->flags &= ~TCB_INSYSCALL;
2380 return res;
2381 }
2382
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002383 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002384 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002385 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002386 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002387 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002388 /* FIXME: not_failing_only (IOW, option -z) is broken:
2389 * failure of syscall is known only after syscall return.
2390 * Thus we end up with something like this on, say, ENOENT:
2391 * open("doesnt_exist", O_RDONLY <unfinished ...>
2392 * {next syscall decode}
2393 * whereas the intended result is that open(...) line
2394 * is not shown at all.
2395 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002396 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002397 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002398 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2399 }
2400
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002401 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002402 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002403 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002404 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002405 qual_flags[tcp->scno] & QUAL_RAW) {
2406 if (u_error)
2407 tprintf("= -1 (errno %ld)", u_error);
2408 else
2409 tprintf("= %#lx", tcp->u_rval);
2410 }
2411 else if (!(sys_res & RVAL_NONE) && u_error) {
2412 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002413 /* Blocked signals do not interrupt any syscalls.
2414 * In this case syscalls don't return ERESTARTfoo codes.
2415 *
2416 * Deadly signals set to SIG_DFL interrupt syscalls
2417 * and kill the process regardless of which of the codes below
2418 * is returned by the interrupted syscall.
2419 * In some cases, kernel forces a kernel-generated deadly
2420 * signal to be unblocked and set to SIG_DFL (and thus cause
2421 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2422 * or SIGILL. (The alternative is to leave process spinning
2423 * forever on the faulty instruction - not useful).
2424 *
2425 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2426 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2427 * but kernel will always restart them.
2428 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002429 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002430 /* Most common type of signal-interrupted syscall exit code.
2431 * The system call will be restarted with the same arguments
2432 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2433 */
2434 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002435 break;
2436 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002437 /* Rare. For example, fork() returns this if interrupted.
2438 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2439 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002440 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002441 break;
2442 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002443 /* pause(), rt_sigsuspend() etc use this code.
2444 * SA_RESTART is ignored (assumed not set):
2445 * syscall won't restart (will return EINTR instead)
2446 * even after signal with SA_RESTART set.
2447 * However, after SIG_IGN or SIG_DFL signal it will.
2448 */
2449 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002450 break;
2451 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002452 /* Syscalls like nanosleep(), poll() which can't be
2453 * restarted with their original arguments use this
2454 * code. Kernel will execute restart_syscall() instead,
2455 * which changes arguments before restarting syscall.
2456 * SA_RESTART is ignored (assumed not set) similarly
2457 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2458 * since restart data is saved in "restart block"
2459 * in task struct, and if signal handler uses a syscall
2460 * which in turn saves another such restart block,
2461 * old data is lost and restart becomes impossible)
2462 */
2463 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002464 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002465 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002466 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002467 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002468 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002469 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002470 strerror(u_error));
2471 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002472 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002473 strerror(u_error));
2474 break;
2475 }
2476 if ((sys_res & RVAL_STR) && tcp->auxstr)
2477 tprintf(" (%s)", tcp->auxstr);
2478 }
2479 else {
2480 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002481 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002482 else {
2483 switch (sys_res & RVAL_MASK) {
2484 case RVAL_HEX:
2485 tprintf("= %#lx", tcp->u_rval);
2486 break;
2487 case RVAL_OCTAL:
2488 tprintf("= %#lo", tcp->u_rval);
2489 break;
2490 case RVAL_UDECIMAL:
2491 tprintf("= %lu", tcp->u_rval);
2492 break;
2493 case RVAL_DECIMAL:
2494 tprintf("= %ld", tcp->u_rval);
2495 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002496#if defined(LINUX_MIPSN32) || defined(X32)
2497 /*
2498 case RVAL_LHEX:
2499 tprintf("= %#llx", tcp->u_lrval);
2500 break;
2501 case RVAL_LOCTAL:
2502 tprintf("= %#llo", tcp->u_lrval);
2503 break;
2504 */
2505 case RVAL_LUDECIMAL:
2506 tprintf("= %llu", tcp->u_lrval);
2507 break;
2508 /*
2509 case RVAL_LDECIMAL:
2510 tprintf("= %lld", tcp->u_lrval);
2511 break;
2512 */
2513#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002514 default:
2515 fprintf(stderr,
2516 "invalid rval format\n");
2517 break;
2518 }
2519 }
2520 if ((sys_res & RVAL_STR) && tcp->auxstr)
2521 tprintf(" (%s)", tcp->auxstr);
2522 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002523 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002524 tv_sub(&tv, &tv, &tcp->etime);
2525 tprintf(" <%ld.%06ld>",
2526 (long) tv.tv_sec, (long) tv.tv_usec);
2527 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002528 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002529 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002530 line_ended();
2531
Denys Vlasenko3b738812011-08-22 02:06:35 +02002532 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002533 tcp->flags &= ~TCB_INSYSCALL;
2534 return 0;
2535}
2536
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002537int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002538trace_syscall(struct tcb *tcp)
2539{
2540 return exiting(tcp) ?
2541 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2542}