blob: ec4856c1dcf39117bdbc155e14a43f8bdcc4e8d0 [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
Steve McIntyred8d3bd32012-10-24 17:58:16 +010068#if defined(AARCH64)
69# include <asm/ptrace.h>
70# include <sys/uio.h>
71# include <elf.h>
72#endif
73
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000074#ifndef ERESTARTSYS
Denys Vlasenko523635f2012-02-25 02:44:25 +010075# define ERESTARTSYS 512
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000076#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010077#ifndef ERESTARTNOINTR
Denys Vlasenko523635f2012-02-25 02:44:25 +010078# define ERESTARTNOINTR 513
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000079#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010080#ifndef ERESTARTNOHAND
81# define ERESTARTNOHAND 514 /* restart if no handler */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000082#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010083#ifndef ERESTART_RESTARTBLOCK
Denys Vlasenko523635f2012-02-25 02:44:25 +010084# define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
Roland McGrath9c555e72003-07-09 09:47:59 +000085#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010086
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000087#ifndef NSIG
Denys Vlasenko523635f2012-02-25 02:44:25 +010088# warning: NSIG is not defined, using 32
89# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000090#endif
91#ifdef ARM
Denys Vlasenko041b3ee2011-08-18 12:48:56 +020092/* Ugh. Is this really correct? ARM has no RT signals?! */
Denys Vlasenko523635f2012-02-25 02:44:25 +010093# undef NSIG
94# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000095#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000096
97#include "syscall.h"
98
99/* Define these shorthand notations to simplify the syscallent files. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000100#define TD TRACE_DESC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000101#define TF TRACE_FILE
102#define TI TRACE_IPC
103#define TN TRACE_NETWORK
104#define TP TRACE_PROCESS
105#define TS TRACE_SIGNAL
Namhyung Kim96792962012-10-24 11:41:57 +0900106#define TM TRACE_MEMORY
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000107#define NF SYSCALL_NEVER_FAILS
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200108#define MA MAX_ARGS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000109
Roland McGrathee36ce12004-09-04 03:53:10 +0000110static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000111#include "syscallent.h"
112};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000113
114#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000115static const struct sysent sysent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100116# include "syscallent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000117};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200118#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000119
120#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000121static const struct sysent sysent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100122# include "syscallent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000123};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200124#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000125
126/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000127#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000128#undef TF
129#undef TI
130#undef TN
131#undef TP
132#undef TS
Namhyung Kim96792962012-10-24 11:41:57 +0900133#undef TM
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000134#undef NF
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200135#undef MA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000136
Denys Vlasenko39fca622011-08-20 02:12:33 +0200137/*
138 * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
139 * program `ioctlsort', such that the list is sorted by the `code' field.
140 * This has the side-effect of resolving the _IO.. macros into
141 * plain integers, eliminating the need to include here everything
142 * in "/usr/include".
143 */
144
Roland McGrathee36ce12004-09-04 03:53:10 +0000145static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000146#include "errnoent.h"
147};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200148static const char *const signalent0[] = {
149#include "signalent.h"
150};
151static const struct ioctlent ioctlent0[] = {
152#include "ioctlent.h"
153};
154enum { nsyscalls0 = ARRAY_SIZE(sysent0) };
155enum { nerrnos0 = ARRAY_SIZE(errnoent0) };
156enum { nsignals0 = ARRAY_SIZE(signalent0) };
157enum { nioctlents0 = ARRAY_SIZE(ioctlent0) };
158int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000159
160#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000161static const char *const errnoent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100162# include "errnoent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000163};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200164static const char *const signalent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100165# include "signalent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200166};
167static const struct ioctlent ioctlent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100168# include "ioctlent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200169};
170enum { nsyscalls1 = ARRAY_SIZE(sysent1) };
171enum { nerrnos1 = ARRAY_SIZE(errnoent1) };
172enum { nsignals1 = ARRAY_SIZE(signalent1) };
173enum { nioctlents1 = ARRAY_SIZE(ioctlent1) };
174int qual_flags1[MAX_QUALS];
175#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000176
177#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000178static const char *const errnoent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100179# include "errnoent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000180};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200181static const char *const signalent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100182# include "signalent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200183};
184static const struct ioctlent ioctlent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100185# include "ioctlent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200186};
187enum { nsyscalls2 = ARRAY_SIZE(sysent2) };
188enum { nerrnos2 = ARRAY_SIZE(errnoent2) };
189enum { nsignals2 = ARRAY_SIZE(signalent2) };
190enum { nioctlents2 = ARRAY_SIZE(ioctlent2) };
191int qual_flags2[MAX_QUALS];
192#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000193
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100194const struct sysent *sysent = sysent0;
195const char *const *errnoent = errnoent0;
196const char *const *signalent = signalent0;
197const struct ioctlent *ioctlent = ioctlent0;
198unsigned nsyscalls = nsyscalls0;
199unsigned nerrnos = nerrnos0;
200unsigned nsignals = nsignals0;
201unsigned nioctlents = nioctlents0;
202int *qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000203
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100204#if SUPPORTED_PERSONALITIES > 1
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000205int current_personality;
206
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000207const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
208 PERSONALITY0_WORDSIZE,
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000209 PERSONALITY1_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100210# if SUPPORTED_PERSONALITIES > 2
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000211 PERSONALITY2_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100212# endif
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200213};
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000214
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200215void
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000216set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000217{
218 switch (personality) {
219 case 0:
220 errnoent = errnoent0;
221 nerrnos = nerrnos0;
222 sysent = sysent0;
223 nsyscalls = nsyscalls0;
224 ioctlent = ioctlent0;
225 nioctlents = nioctlents0;
226 signalent = signalent0;
227 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000228 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000229 break;
230
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000231 case 1:
232 errnoent = errnoent1;
233 nerrnos = nerrnos1;
234 sysent = sysent1;
235 nsyscalls = nsyscalls1;
236 ioctlent = ioctlent1;
237 nioctlents = nioctlents1;
238 signalent = signalent1;
239 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000240 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000241 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000242
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100243# if SUPPORTED_PERSONALITIES >= 3
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000244 case 2:
245 errnoent = errnoent2;
246 nerrnos = nerrnos2;
247 sysent = sysent2;
248 nsyscalls = nsyscalls2;
249 ioctlent = ioctlent2;
250 nioctlents = nioctlents2;
251 signalent = signalent2;
252 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000253 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000254 break;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100255# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000256 }
257
258 current_personality = personality;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000259}
260
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000261static void
262update_personality(struct tcb *tcp, int personality)
263{
264 if (personality == current_personality)
265 return;
266 set_personality(personality);
267
268 if (personality == tcp->currpers)
269 return;
270 tcp->currpers = personality;
271
H.J. Lu35be5812012-04-16 13:00:01 +0200272# if defined(POWERPC64)
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000273 if (!qflag) {
274 static const char *const names[] = {"64 bit", "32 bit"};
275 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
276 tcp->pid, names[personality]);
277 }
H.J. Lu35be5812012-04-16 13:00:01 +0200278# elif defined(X86_64)
279 if (!qflag) {
280 static const char *const names[] = {"64 bit", "32 bit", "x32"};
281 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
282 tcp->pid, names[personality]);
283 }
H.J. Lu085e4282012-04-17 11:05:04 -0700284# elif defined(X32)
285 if (!qflag) {
286 static const char *const names[] = {"x32", "32 bit"};
287 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
288 tcp->pid, names[personality]);
289 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000290# elif defined(AARCH64)
291 if (!qflag) {
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100292 static const char *const names[] = {"32-bit", "AArch64"};
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000293 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
294 tcp->pid, names[personality]);
295 }
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100296# elif defined(TILE)
297 if (!qflag) {
298 static const char *const names[] = {"64-bit", "32-bit"};
299 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
300 tcp->pid, names[personality]);
301 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100302# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000303}
304#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000305
Roland McGrath9797ceb2002-12-30 10:23:00 +0000306static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000307
Roland McGrathe10e62a2004-09-04 04:20:43 +0000308static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000309 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000310 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000311 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000312 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000313} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000314 { QUAL_TRACE, "trace", qual_syscall, "system call" },
315 { QUAL_TRACE, "t", qual_syscall, "system call" },
316 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
317 { QUAL_ABBREV, "a", qual_syscall, "system call" },
318 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
319 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
320 { QUAL_RAW, "raw", qual_syscall, "system call" },
321 { QUAL_RAW, "x", qual_syscall, "system call" },
322 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
323 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
324 { QUAL_SIGNAL, "s", qual_signal, "signal" },
325 { QUAL_FAULT, "fault", qual_fault, "fault" },
326 { QUAL_FAULT, "faults", qual_fault, "fault" },
327 { QUAL_FAULT, "m", qual_fault, "fault" },
328 { QUAL_READ, "read", qual_desc, "descriptor" },
329 { QUAL_READ, "reads", qual_desc, "descriptor" },
330 { QUAL_READ, "r", qual_desc, "descriptor" },
331 { QUAL_WRITE, "write", qual_desc, "descriptor" },
332 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
333 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000334 { 0, NULL, NULL, NULL },
335};
336
Roland McGrath9797ceb2002-12-30 10:23:00 +0000337static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000338qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000339{
Roland McGrath138c6a32006-01-12 09:50:49 +0000340 if (pers == 0 || pers < 0) {
341 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000342 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000343 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000344 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000345 }
346
347#if SUPPORTED_PERSONALITIES >= 2
348 if (pers == 1 || pers < 0) {
349 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000350 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000351 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000352 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000353 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100354#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000355
356#if SUPPORTED_PERSONALITIES >= 3
357 if (pers == 2 || pers < 0) {
358 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000359 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000360 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000361 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000362 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100363#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000364}
365
366static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000367qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000368{
369 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000370 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000371
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100372 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000373 int i = string_to_uint(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000374 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000375 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000376 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000377 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000378 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000379 for (i = 0; i < nsyscalls0; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000380 if (sysent0[i].sys_name &&
381 strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000382 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000383 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000384 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000385
386#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000387 for (i = 0; i < nsyscalls1; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000388 if (sysent1[i].sys_name &&
389 strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000390 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000391 rc = 0;
392 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100393#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000394
395#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000396 for (i = 0; i < nsyscalls2; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000397 if (sysent2[i].sys_name &&
398 strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000399 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000400 rc = 0;
401 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100402#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000403
Roland McGrathfe6b3522005-02-02 04:40:11 +0000404 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000405}
406
407static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000408qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000409{
410 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000411
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100412 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000413 int signo = string_to_uint(s);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000414 if (signo < 0 || signo >= MAX_QUALS)
415 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000416 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000417 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000418 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000419 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000420 s += 3;
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100421 for (i = 0; i <= NSIG; i++) {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000422 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000423 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000424 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000425 }
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100426 }
Roland McGrath76421df2005-02-02 03:51:18 +0000427 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000428}
429
430static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000431qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000432{
433 return -1;
434}
435
436static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000437qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000438{
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100439 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000440 int desc = string_to_uint(s);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000441 if (desc < 0 || desc >= MAX_QUALS)
442 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000443 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000444 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000445 }
446 return -1;
447}
448
449static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000450lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000451{
452 if (strcmp(s, "file") == 0)
453 return TRACE_FILE;
454 if (strcmp(s, "ipc") == 0)
455 return TRACE_IPC;
456 if (strcmp(s, "network") == 0)
457 return TRACE_NETWORK;
458 if (strcmp(s, "process") == 0)
459 return TRACE_PROCESS;
460 if (strcmp(s, "signal") == 0)
461 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000462 if (strcmp(s, "desc") == 0)
463 return TRACE_DESC;
Namhyung Kim96792962012-10-24 11:41:57 +0900464 if (strcmp(s, "memory") == 0)
465 return TRACE_MEMORY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000466 return -1;
467}
468
469void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000470qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000471{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000472 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000473 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000474 char *copy;
475 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000476 int i, n;
477
478 opt = &qual_options[0];
479 for (i = 0; (p = qual_options[i].option_name); i++) {
480 n = strlen(p);
481 if (strncmp(s, p, n) == 0 && s[n] == '=') {
482 opt = &qual_options[i];
483 s += n + 1;
484 break;
485 }
486 }
487 not = 0;
488 if (*s == '!') {
489 not = 1;
490 s++;
491 }
492 if (strcmp(s, "none") == 0) {
493 not = 1 - not;
494 s = "all";
495 }
496 if (strcmp(s, "all") == 0) {
497 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000498 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000499 }
500 return;
501 }
502 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000503 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000504 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200505 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200506 if (!copy)
507 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000508 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000509 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000510 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000511 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000512 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000513
514#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000515 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000516 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000517 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100518#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000519
520#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000521 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000522 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000523 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100524#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000525
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000526 continue;
527 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000528 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100529 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000530 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000531 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000532 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000533 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000534 return;
535}
536
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000537#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000538static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000539decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000540{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000541 unsigned long addr;
542 unsigned int i, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000543
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000544 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
545 return;
546
547 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
548 addr = tcp->u_arg[1];
549 tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100550 size = current_wordsize;
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000551 for (i = 0; i < tcp->u_nargs; ++i) {
552 if (size == sizeof(int)) {
553 unsigned int arg;
554 if (umove(tcp, addr, &arg) < 0)
555 arg = 0;
556 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000557 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000558 else {
559 unsigned long arg;
560 if (umove(tcp, addr, &arg) < 0)
561 arg = 0;
562 tcp->u_arg[i] = arg;
563 }
564 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000565 }
566}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000567#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400568
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000569#ifdef SYS_ipc_subcall
570static void
571decode_ipc_subcall(struct tcb *tcp)
572{
573 unsigned int i;
574
575 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
576 return;
577
578 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
579 tcp->u_nargs = sysent[tcp->scno].nargs;
580 for (i = 0; i < tcp->u_nargs; i++)
581 tcp->u_arg[i] = tcp->u_arg[i + 1];
582}
583#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000584
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200585int
586printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000587{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200588 if (entering(tcp)) {
589 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000590
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200591 for (i = 0; i < tcp->u_nargs; i++)
592 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
593 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000594 return 0;
595}
596
Denys Vlasenko72879c62012-02-27 14:18:02 +0100597int
598printargs_lu(struct tcb *tcp)
599{
600 if (entering(tcp)) {
601 int i;
602
603 for (i = 0; i < tcp->u_nargs; i++)
604 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
605 }
606 return 0;
607}
608
609int
610printargs_ld(struct tcb *tcp)
611{
612 if (entering(tcp)) {
613 int i;
614
615 for (i = 0; i < tcp->u_nargs; i++)
616 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
617 }
618 return 0;
619}
620
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100621#if defined(SPARC) || defined(SPARC64) || defined(IA64) || defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200622long
623getrval2(struct tcb *tcp)
624{
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100625 long val;
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200626
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100627# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200628 val = regs.u_regs[U_REG_O1];
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100629# elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200630 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
631 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100632# elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200633 if (upeek(tcp, PT_R9, &val) < 0)
634 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100635# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200636
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200637 return val;
638}
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100639#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200640
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200641int
642is_restart_error(struct tcb *tcp)
643{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200644 switch (tcp->u_error) {
645 case ERESTARTSYS:
646 case ERESTARTNOINTR:
647 case ERESTARTNOHAND:
648 case ERESTART_RESTARTBLOCK:
649 return 1;
650 default:
651 break;
652 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200653 return 0;
654}
655
Denys Vlasenko523635f2012-02-25 02:44:25 +0100656#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100657struct pt_regs i386_regs;
H.J. Lu35be5812012-04-16 13:00:01 +0200658#elif defined(X86_64) || defined(X32)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100659/*
660 * On 32 bits, pt_regs and user_regs_struct are the same,
661 * but on 64 bits, user_regs_struct has six more fields:
662 * fs_base, gs_base, ds, es, fs, gs.
663 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
664 */
665static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100666#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200667long ia32 = 0; /* not static */
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100668static long ia64_r8, ia64_r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100669#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +0100670static long ppc_result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100671#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100672static long m68k_d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100673#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100674static long bfin_r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100675#elif defined(ARM)
Denys Vlasenko401374e2013-02-06 18:24:39 +0100676struct pt_regs arm_regs; /* not static */
Steve McIntyred8d3bd32012-10-24 17:58:16 +0100677#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100678static union {
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100679 struct user_pt_regs aarch64_r;
680 struct arm_pt_regs arm_r;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100681} arm_regs_union;
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100682# define aarch64_regs arm_regs_union.aarch64_r
683# define arm_regs arm_regs_union.arm_r
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100684static struct iovec aarch64_io = {
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100685 .iov_base = &arm_regs_union
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100686};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100687#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100688static long alpha_r0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100689static long alpha_a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100690#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200691static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100692#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100693struct pt_regs regs; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100694#elif defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100695static long long mips_a3;
696static long long mips_r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100697#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100698static long mips_a3;
699static long mips_r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100700#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200701static long gpr2;
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200702static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100703#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100704static long hppa_r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100705#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100706static long sh_r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100707#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100708static long sh64_r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100709#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100710static long cris_r10;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100711#elif defined(TILE)
712struct pt_regs tile_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100713#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100714static long microblaze_r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100715#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000716
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100717void
718printcall(struct tcb *tcp)
719{
720#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
721 sizeof(long) == 8 ? "[????????????????] " : \
722 NULL /* crash */)
723 if (get_regs_error) {
724 PRINTBADPC;
725 return;
726 }
727#if defined(I386)
728 tprintf("[%08lx] ", i386_regs.eip);
729#elif defined(S390) || defined(S390X)
730 long psw;
731 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
732 PRINTBADPC;
733 return;
734 }
735# ifdef S390
736 tprintf("[%08lx] ", psw);
737# elif S390X
Dmitry V. Levinddba73e2013-02-05 19:01:58 +0000738 tprintf("[%016lx] ", psw);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100739# endif
740#elif defined(X86_64) || defined(X32)
Dmitry V. Levinddba73e2013-02-05 19:01:58 +0000741 tprintf("[%016lx] ", (unsigned long) x86_64_regs.rip);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100742#elif defined(IA64)
743 long ip;
744
745 if (upeek(tcp, PT_B0, &ip) < 0) {
746 PRINTBADPC;
747 return;
748 }
749 tprintf("[%08lx] ", ip);
750#elif defined(POWERPC)
751 long pc;
752
753 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
754 PRINTBADPC;
755 return;
756 }
757# ifdef POWERPC64
758 tprintf("[%016lx] ", pc);
759# else
760 tprintf("[%08lx] ", pc);
761# endif
762#elif defined(M68K)
763 long pc;
764
765 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
766 tprints("[????????] ");
767 return;
768 }
769 tprintf("[%08lx] ", pc);
770#elif defined(ALPHA)
771 long pc;
772
773 if (upeek(tcp, REG_PC, &pc) < 0) {
774 tprints("[????????????????] ");
775 return;
776 }
777 tprintf("[%08lx] ", pc);
778#elif defined(SPARC)
779 tprintf("[%08lx] ", regs.pc);
780#elif defined(SPARC64)
781 tprintf("[%08lx] ", regs.tpc);
782#elif defined(HPPA)
783 long pc;
784
785 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
786 tprints("[????????] ");
787 return;
788 }
789 tprintf("[%08lx] ", pc);
790#elif defined(MIPS)
791 long pc;
792
793 if (upeek(tcp, REG_EPC, &pc) < 0) {
794 tprints("[????????] ");
795 return;
796 }
797 tprintf("[%08lx] ", pc);
798#elif defined(SH)
799 long pc;
800
801 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
802 tprints("[????????] ");
803 return;
804 }
805 tprintf("[%08lx] ", pc);
806#elif defined(SH64)
807 long pc;
808
809 if (upeek(tcp, REG_PC, &pc) < 0) {
810 tprints("[????????????????] ");
811 return;
812 }
813 tprintf("[%08lx] ", pc);
814#elif defined(ARM)
Denys Vlasenko401374e2013-02-06 18:24:39 +0100815 tprintf("[%08lx] ", arm_regs.ARM_pc);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100816#elif defined(AARCH64)
817 /* tprintf("[%016lx] ", aarch64_regs.regs[???]); */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100818#elif defined(AVR32)
819 tprintf("[%08lx] ", regs.pc);
820#elif defined(BFIN)
821 long pc;
822
823 if (upeek(tcp, PT_PC, &pc) < 0) {
824 PRINTBADPC;
825 return;
826 }
827 tprintf("[%08lx] ", pc);
828#elif defined(CRISV10)
829 long pc;
830
831 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
832 PRINTBADPC;
833 return;
834 }
835 tprintf("[%08lx] ", pc);
836#elif defined(CRISV32)
837 long pc;
838
839 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
840 PRINTBADPC;
841 return;
842 }
843 tprintf("[%08lx] ", pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100844#elif defined(TILE)
845# ifdef _LP64
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500846 tprintf("[%016lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100847# else
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500848 tprintf("[%08lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100849# endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100850#endif /* architecture */
851}
852
853#ifndef get_regs
854long get_regs_error;
855void get_regs(pid_t pid)
856{
857# if defined(AVR32)
858 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
859# elif defined(I386)
860 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &i386_regs);
861# elif defined(X86_64) || defined(X32)
862 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &x86_64_regs);
Denys Vlasenko401374e2013-02-06 18:24:39 +0100863# elif defined(ARM)
864 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (void *)&arm_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100865# elif defined(AARCH64)
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100866 /*aarch64_io.iov_base = &arm_regs_union; - already is */
867 aarch64_io.iov_len = sizeof(arm_regs_union);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100868 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void *)&aarch64_io);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100869# if 0
870 /* Paranoia checks */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100871 if (get_regs_error)
872 return;
873 switch (aarch64_io.iov_len) {
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100874 case sizeof(aarch64_regs):
875 /* We are in 64-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100876 break;
877 case sizeof(arm_regs):
878 /* We are in 32-bit mode */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100879 break;
880 default:
881 get_regs_error = -1;
882 break;
883 }
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100884# endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100885# elif defined(SPARC) || defined(SPARC64)
886 get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&regs, 0);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100887# elif defined(TILE)
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500888 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &tile_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100889# endif
890}
891#endif
892
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200893/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100894 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
895 * 1: ok, continue in trace_syscall_entering().
896 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200897 * ("????" etc) and bail out.
898 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100899static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200900get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000901{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000902 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000903
Denys Vlasenko523635f2012-02-25 02:44:25 +0100904#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000905 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200906 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000907
908 if (syscall_mode != -ENOSYS) {
909 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000910 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000911 */
912 scno = syscall_mode;
913 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000914 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000915 * Old style of "passing" the scno via the SVC instruction.
916 */
Denys Vlasenko7ba8e722013-02-08 15:50:05 +0100917 long psw;
Michal Ludvig882eda82002-11-11 12:50:47 +0000918 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200919 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200920 static const int gpr_offset[16] = {
921 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
922 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
923 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
924 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
925 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000926
Denys Vlasenko7ba8e722013-02-08 15:50:05 +0100927 if (upeek(tcp, PT_PSWADDR, &psw) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000928 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000929 errno = 0;
Denys Vlasenko7ba8e722013-02-08 15:50:05 +0100930 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(psw - sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000931 if (errno) {
Denys Vlasenko7ba8e722013-02-08 15:50:05 +0100932 perror_msg("%s", "peektext(psw-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000933 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000934 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000935
936 /*
937 * We have to check if the SVC got executed directly or via an
938 * EXECUTE instruction. In case of EXECUTE it is necessary to do
939 * instruction decoding to derive the system call number.
940 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
941 * so that this doesn't work if a SVC opcode is part of an EXECUTE
942 * opcode. Since there is no way to find out the opcode size this
943 * is the best we can do...
944 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000945 if ((opcode & 0xff00) == 0x0a00) {
946 /* SVC opcode */
947 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000948 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000949 else {
950 /* SVC got executed by EXECUTE instruction */
951
952 /*
953 * Do instruction decoding of EXECUTE. If you really want to
954 * understand this, read the Principles of Operations.
955 */
956 svc_addr = (void *) (opcode & 0xfff);
957
958 tmp = 0;
959 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000960 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000961 return -1;
962 svc_addr += tmp;
963
964 tmp = 0;
965 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000966 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000967 return -1;
968 svc_addr += tmp;
969
Denys Vlasenkofb036672009-01-23 16:30:26 +0000970 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000971 if (errno)
972 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100973# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000974 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100975# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000976 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100977# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000978 tmp = 0;
979 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000980 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000981 return -1;
982
983 scno = (scno | tmp) & 0xff;
984 }
985 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100986#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000987 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000988 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100989# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200990 /* TODO: speed up strace by not doing this at every syscall.
991 * We only need to do it after execve.
992 */
993 int currpers;
994 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200995
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200996 /* Check for 64/32 bit mode. */
997 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
998 return -1;
999 /* SF is bit 0 of MSR */
1000 if (val < 0)
1001 currpers = 0;
1002 else
1003 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001004 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001005# endif
1006#elif defined(AVR32)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001007 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001008#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001009 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001010 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001011#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001012 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +02001013#elif defined(X86_64) || defined(X32)
1014# ifndef __X32_SYSCALL_BIT
1015# define __X32_SYSCALL_BIT 0x40000000
1016# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001017 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001018 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +00001019
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001020 /* Check CS register value. On x86-64 linux it is:
1021 * 0x33 for long mode (64 bit)
1022 * 0x23 for compatibility mode (32 bit)
H.J. Lu35be5812012-04-16 13:00:01 +02001023 * Check DS register value. On x86-64 linux it is:
1024 * 0x2b for x32 mode (x86-64 in 32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001025 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001026 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001027 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +02001028 case 0x33:
1029 if (x86_64_regs.ds == 0x2b) {
1030 currpers = 2;
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001031 scno &= ~__X32_SYSCALL_BIT;
H.J. Lu35be5812012-04-16 13:00:01 +02001032 } else
1033 currpers = 0;
1034 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001035 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001036 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001037 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001038 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001039 currpers = current_personality;
1040 break;
1041 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001042# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001043 /* This version analyzes the opcode of a syscall instruction.
1044 * (int 0x80 on i386 vs. syscall on x86-64)
1045 * It works, but is too complicated.
1046 */
1047 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +00001048
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001049 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +00001050
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001051 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
1052 rip -= 2;
1053 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +00001054
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001055 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001056 if (errno)
1057 fprintf(stderr, "ptrace_peektext failed: %s\n",
1058 strerror(errno));
1059 switch (call & 0xffff) {
1060 /* x86-64: syscall = 0x0f 0x05 */
1061 case 0x050f: currpers = 0; break;
1062 /* i386: int 0x80 = 0xcd 0x80 */
1063 case 0x80cd: currpers = 1; break;
1064 default:
1065 currpers = current_personality;
1066 fprintf(stderr,
1067 "Unknown syscall opcode (0x%04X) while "
1068 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001069 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001070 break;
1071 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001072# endif
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001073
H.J. Lu35be5812012-04-16 13:00:01 +02001074# ifdef X32
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001075 /* If we are built for a x32 system, then personality 0 is x32
1076 * (not x86_64), and stracing of x86_64 apps is not supported.
1077 * Stracing of i386 apps is still supported.
H.J. Lu085e4282012-04-17 11:05:04 -07001078 */
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001079 if (currpers == 0) {
1080 fprintf(stderr, "syscall_%lu(...) in unsupported "
1081 "64-bit mode of process PID=%d\n",
1082 scno, tcp->pid);
1083 return 0;
H.J. Lu35be5812012-04-16 13:00:01 +02001084 }
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001085 currpers &= ~2; /* map 2,1 to 0,1 */
H.J. Lu35be5812012-04-16 13:00:01 +02001086# endif
H.J. Lu085e4282012-04-17 11:05:04 -07001087 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001088#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001089# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001090 long psr;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001091 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001092 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001093 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001094 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001095 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001096 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001097 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001098 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001099 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001100#elif defined(AARCH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001101 switch (aarch64_io.iov_len) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001102 case sizeof(aarch64_regs):
1103 /* We are in 64-bit mode */
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001104 scno = aarch64_regs.regs[8];
1105 update_personality(tcp, 1);
1106 break;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001107 case sizeof(arm_regs):
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001108 /* We are in 32-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001109 scno = arm_regs.ARM_r7;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001110 update_personality(tcp, 0);
1111 break;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001112 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001113#elif defined(ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001114 /*
1115 * We only need to grab the syscall number on syscall entry.
1116 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001117 if (arm_regs.ARM_ip == 0) {
Roland McGrath0f87c492003-06-03 23:29:04 +00001118 /*
Denys Vlasenko401374e2013-02-06 18:24:39 +01001119 * Note: we only deal with 32-bit CPUs here
Roland McGrath0f87c492003-06-03 23:29:04 +00001120 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001121 if (arm_regs.ARM_cpsr & 0x20) {
Roland McGrath0f87c492003-06-03 23:29:04 +00001122 /*
1123 * Get the Thumb-mode system call number
1124 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001125 scno = arm_regs.ARM_r7;
Roland McGrath0f87c492003-06-03 23:29:04 +00001126 } else {
1127 /*
1128 * Get the ARM-mode system call number
1129 */
1130 errno = 0;
Denys Vlasenko401374e2013-02-06 18:24:39 +01001131 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(arm_regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +00001132 if (errno)
1133 return -1;
1134
Roland McGrathf691bd22006-04-25 07:34:41 +00001135 /* Handle the EABI syscall convention. We do not
1136 bother converting structures between the two
1137 ABIs, but basic functionality should work even
1138 if strace and the traced program have different
1139 ABIs. */
1140 if (scno == 0xef000000) {
Denys Vlasenko401374e2013-02-06 18:24:39 +01001141 scno = arm_regs.ARM_r7;
Roland McGrathf691bd22006-04-25 07:34:41 +00001142 } else {
1143 if ((scno & 0x0ff00000) != 0x0f900000) {
1144 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1145 scno);
1146 return -1;
1147 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001148
Roland McGrathf691bd22006-04-25 07:34:41 +00001149 /*
1150 * Fixup the syscall number
1151 */
1152 scno &= 0x000fffff;
1153 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001154 }
Roland McGrath56703312008-05-20 01:35:55 +00001155 if (scno & 0x0f0000) {
1156 /*
1157 * Handle ARM specific syscall
1158 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001159 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +00001160 scno &= 0x0000ffff;
1161 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001162 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001163
Roland McGrath0f87c492003-06-03 23:29:04 +00001164 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001165 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1166 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001167 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001168#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001169 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001170 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001171#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001172 unsigned long long regs[38];
1173
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001174 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001175 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001176 mips_a3 = regs[REG_A3];
1177 mips_r2 = regs[REG_V0];
Roland McGrath542c2c62008-05-20 01:11:56 +00001178
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001179 scno = mips_r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001180 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001181 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001182 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001183 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001184 return 0;
1185 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001186 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001187#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001188 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001189 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001190 if (upeek(tcp, REG_V0, &scno) < 0)
1191 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001192
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001193 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001194 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001195 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001196 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001197 return 0;
1198 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001199 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001200#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001201 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001202 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001203 if (upeek(tcp, REG_R0, &scno) < 0)
1204 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001205
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001206 /*
1207 * Do some sanity checks to figure out if it's
1208 * really a syscall entry
1209 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001210 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001211 if (alpha_a3 == 0 || alpha_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001212 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001213 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001214 return 0;
1215 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001216 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001217#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001218 /* Disassemble the syscall trap. */
1219 /* Retrieve the syscall trap instruction. */
Denys Vlasenko46455822013-02-05 17:02:59 +01001220 unsigned long trap;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001221 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001222# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001223 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1224 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001225# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001226 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001227# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001228 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001229 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001230
1231 /* Disassemble the trap to see what personality to use. */
1232 switch (trap) {
1233 case 0x91d02010:
1234 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001235 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001236 break;
1237 case 0x91d0206d:
1238 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001239 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001240 break;
1241 case 0x91d02000:
1242 /* SunOS syscall trap. (pers 1) */
1243 fprintf(stderr, "syscall: SunOS no support\n");
1244 return -1;
1245 case 0x91d02008:
1246 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001247 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001248 break;
1249 case 0x91d02009:
1250 /* NetBSD/FreeBSD syscall trap. */
1251 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1252 return -1;
1253 case 0x91d02027:
1254 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001255 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001256 break;
1257 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001258# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001259 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001260# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001261 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001262# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001263 return -1;
1264 }
1265
1266 /* Extract the system call number from the registers. */
1267 if (trap == 0x91d02027)
1268 scno = 156;
1269 else
1270 scno = regs.u_regs[U_REG_G1];
1271 if (scno == 0) {
1272 scno = regs.u_regs[U_REG_O0];
1273 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1274 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001275#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001276 if (upeek(tcp, PT_GR20, &scno) < 0)
1277 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001278#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001279 /*
1280 * In the new syscall ABI, the system call number is in R3.
1281 */
1282 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1283 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001284
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001285 if (scno < 0) {
1286 /* Odd as it may seem, a glibc bug has been known to cause
1287 glibc to issue bogus negative syscall numbers. So for
1288 our purposes, make strace print what it *should* have been */
1289 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001290 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001291 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001292 "Detected glibc bug: bogus system call"
1293 " number = %ld, correcting to %ld\n",
1294 scno,
1295 correct_scno);
1296 scno = correct_scno;
1297 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001298#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001299 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001300 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001301 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001302#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001303 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1304 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001305#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001306 int currpers;
1307 scno = tile_regs.regs[10];
1308# ifdef __tilepro__
1309 currpers = 1;
1310# else
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001311# ifndef PT_FLAGS_COMPAT
1312# define PT_FLAGS_COMPAT 0x10000 /* from Linux 3.8 on */
1313# endif
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001314 if (tile_regs.flags & PT_FLAGS_COMPAT)
1315 currpers = 1;
1316 else
1317 currpers = 0;
1318# endif
1319 update_personality(tcp, currpers);
1320
1321 if (!(tcp->flags & TCB_INSYSCALL)) {
1322 /* Check if we return from execve. */
1323 if (tcp->flags & TCB_WAITEXECVE) {
1324 tcp->flags &= ~TCB_WAITEXECVE;
1325 return 0;
1326 }
1327 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001328#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001329 if (upeek(tcp, 0, &scno) < 0)
1330 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001331#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001332
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001333 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001334 return 1;
1335}
1336
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001337/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001338 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001339 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1340 * 1: ok, continue in trace_syscall_entering().
1341 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001342 * ("????" etc) and bail out.
1343 */
Roland McGratha4d48532005-06-08 20:45:28 +00001344static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001345syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001346{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001347 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001348#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001349 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001350 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001351 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1352 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001353 }
H.J. Lu35be5812012-04-16 13:00:01 +02001354#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001355 {
1356 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001357 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001358 rax = (int)rax; /* sign extend from 32 bits */
1359 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001360 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001361 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1362 return 0;
1363 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001364 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001365#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001366 /* TODO: we already fetched PT_GPR2 in get_scno
1367 * and stored it in syscall_mode, reuse it here
1368 * instead of re-fetching?
1369 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001370 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001371 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001372 if (syscall_mode != -ENOSYS)
1373 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001374 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001375 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001376 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001377 return 0;
1378 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001379#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001380 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001381 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001382 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001383 if (m68k_d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001384 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001385 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", m68k_d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001386 return 0;
1387 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001388#elif defined(IA64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001389 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001390 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001391 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001392 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001393 if (ia32 && ia64_r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001394 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001395 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", ia64_r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001396 return 0;
1397 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001398#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001399 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001400 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001401 if (cris_r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001402 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001403 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", cris_r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001404 return 0;
1405 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001406#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001407 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001408 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001409 if (microblaze_r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001410 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001411 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", microblaze_r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001412 return 0;
1413 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001414#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001415 return 1;
1416}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001417
Denys Vlasenko146b9442012-03-18 22:10:48 +01001418static void
1419internal_fork(struct tcb *tcp)
1420{
1421#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1422# define ARG_FLAGS 1
1423#else
1424# define ARG_FLAGS 0
1425#endif
1426#ifndef CLONE_UNTRACED
1427# define CLONE_UNTRACED 0x00800000
1428#endif
1429 if ((ptrace_setoptions
1430 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1431 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1432 return;
1433
1434 if (!followfork)
1435 return;
1436
1437 if (entering(tcp)) {
1438 /*
1439 * We won't see the new child if clone is called with
1440 * CLONE_UNTRACED, so we keep the same logic with that option
1441 * and don't trace it.
1442 */
1443 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1444 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1445 return;
1446 setbpt(tcp);
1447 } else {
1448 if (tcp->flags & TCB_BPTSET)
1449 clearbpt(tcp);
1450 }
1451}
1452
1453#if defined(TCB_WAITEXECVE)
1454static void
1455internal_exec(struct tcb *tcp)
1456{
1457 /* Maybe we have post-execve SIGTRAP suppressed? */
1458 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1459 return; /* yes, no need to do anything */
1460
1461 if (exiting(tcp) && syserror(tcp))
1462 /* Error in execve, no post-execve SIGTRAP expected */
1463 tcp->flags &= ~TCB_WAITEXECVE;
1464 else
1465 tcp->flags |= TCB_WAITEXECVE;
1466}
1467#endif
1468
1469static void
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001470syscall_fixup_for_fork_exec(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001471{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001472 /*
1473 * We must always trace a few critical system calls in order to
1474 * correctly support following forks in the presence of tracing
1475 * qualifiers.
1476 */
1477 int (*func)();
1478
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001479 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001480 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001481
1482 func = sysent[tcp->scno].sys_func;
1483
1484 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001485 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001486 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001487 ) {
1488 internal_fork(tcp);
1489 return;
1490 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001491
Denys Vlasenko84703742012-02-25 02:38:52 +01001492#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001493 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001494# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001495 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001496# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001497 ) {
1498 internal_exec(tcp);
1499 return;
1500 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001501#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001502}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001503
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001504/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001505static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001506get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001507{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001508 int i, nargs;
1509
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001510 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001511 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001512 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001513 nargs = tcp->u_nargs = MAX_ARGS;
1514
Denys Vlasenko523635f2012-02-25 02:44:25 +01001515#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001516 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001517 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1518 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001519#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001520 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001521 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1522 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001523#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001524 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001525 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001526 long rbs_end;
1527 /* be backwards compatible with kernel < 2.4.4... */
1528# ifndef PT_RBS_END
1529# define PT_RBS_END PT_AR_BSP
1530# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001531
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001532 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1533 return -1;
1534 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001535 return -1;
1536
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001537 sof = (cfm >> 0) & 0x7f;
1538 sol = (cfm >> 7) & 0x7f;
1539 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1540
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001541 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001542 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1543 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1544 return -1;
1545 }
1546 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001547 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1548 PT_R9 /* ECX = out1 */,
1549 PT_R10 /* EDX = out2 */,
1550 PT_R14 /* ESI = out3 */,
1551 PT_R15 /* EDI = out4 */,
1552 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001553
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001554 for (i = 0; i < nargs; ++i) {
1555 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1556 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001557 /* truncate away IVE sign-extension */
1558 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001559 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001560 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001561#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001562 /* N32 and N64 both use up to six registers. */
1563 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001564
1565 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1566 return -1;
1567
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001568 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001569 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001570# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001571 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001572# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001573 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001574#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001575 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001576 long sp;
1577
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001578 if (upeek(tcp, REG_SP, &sp) < 0)
1579 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001580 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001581 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1582 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001583 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001584 (char *)(tcp->u_arg + 4));
1585 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001586 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001587 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001588 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001589 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001590#elif defined(POWERPC)
1591# ifndef PT_ORIG_R3
1592# define PT_ORIG_R3 34
1593# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001594 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001595 if (upeek(tcp, (i==0) ?
1596 (sizeof(unsigned long) * PT_ORIG_R3) :
1597 ((i+PT_R3) * sizeof(unsigned long)),
1598 &tcp->u_arg[i]) < 0)
1599 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001600 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001601#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001602 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001603 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001604#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001605 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001606 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1607 return -1;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001608#elif defined(ARM) || defined(AARCH64)
1609# if defined(AARCH64)
1610 if (tcp->currpers == 1)
1611 for (i = 0; i < nargs; ++i)
1612 tcp->u_arg[i] = aarch64_regs.regs[i];
1613 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001614# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001615 for (i = 0; i < nargs; ++i)
Denys Vlasenko401374e2013-02-06 18:24:39 +01001616 tcp->u_arg[i] = arm_regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001617#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001618 (void)i;
1619 (void)nargs;
1620 tcp->u_arg[0] = regs.r12;
1621 tcp->u_arg[1] = regs.r11;
1622 tcp->u_arg[2] = regs.r10;
1623 tcp->u_arg[3] = regs.r9;
1624 tcp->u_arg[4] = regs.r5;
1625 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001626#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001627 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 +02001628
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001629 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001630 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1631 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001632#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001633 static const int syscall_regs[MAX_ARGS] = {
1634 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1635 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001636 };
1637
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001638 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001639 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001640 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001641#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001642 int i;
1643 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001644 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001645
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001646 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001647 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1648 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001649#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001650 (void)i;
1651 (void)nargs;
H.J. Lu35be5812012-04-16 13:00:01 +02001652 if (current_personality != 1) { /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001653 tcp->u_arg[0] = x86_64_regs.rdi;
1654 tcp->u_arg[1] = x86_64_regs.rsi;
1655 tcp->u_arg[2] = x86_64_regs.rdx;
1656 tcp->u_arg[3] = x86_64_regs.r10;
1657 tcp->u_arg[4] = x86_64_regs.r8;
1658 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001659# ifdef X32
1660 tcp->ext_arg[0] = x86_64_regs.rdi;
1661 tcp->ext_arg[1] = x86_64_regs.rsi;
1662 tcp->ext_arg[2] = x86_64_regs.rdx;
1663 tcp->ext_arg[3] = x86_64_regs.r10;
1664 tcp->ext_arg[4] = x86_64_regs.r8;
1665 tcp->ext_arg[5] = x86_64_regs.r9;
1666# endif
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001667 } else { /* i386 ABI */
1668 /* Sign-extend lower 32 bits */
1669 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1670 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1671 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1672 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1673 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1674 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1675 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001676#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001677 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001678 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1679 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001680#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001681 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001682 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001683 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001684 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001685
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001686 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001687 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1688 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001689#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001690 for (i = 0; i < nargs; ++i)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001691 tcp->u_arg[i] = tile_regs.regs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001692#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001693 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001694 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1695 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001696#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001697 (void)i;
1698 (void)nargs;
1699 tcp->u_arg[0] = i386_regs.ebx;
1700 tcp->u_arg[1] = i386_regs.ecx;
1701 tcp->u_arg[2] = i386_regs.edx;
1702 tcp->u_arg[3] = i386_regs.esi;
1703 tcp->u_arg[4] = i386_regs.edi;
1704 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001705#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001706 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001707 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1708 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001709#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001710 return 1;
1711}
1712
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001713static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001714trace_syscall_entering(struct tcb *tcp)
1715{
1716 int res, scno_good;
1717
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001718#if defined TCB_WAITEXECVE
1719 if (tcp->flags & TCB_WAITEXECVE) {
1720 /* This is the post-execve SIGTRAP. */
1721 tcp->flags &= ~TCB_WAITEXECVE;
1722 return 0;
1723 }
1724#endif
1725
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001726 scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001727 if (res == 0)
1728 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001729 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001730 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001731 if (res == 0)
1732 return res;
1733 if (res == 1)
1734 res = get_syscall_args(tcp);
1735 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001736
1737 if (res != 1) {
1738 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001739 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001740 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001741 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001742 tprintf("syscall_%lu(", tcp->scno);
1743 else
1744 tprintf("%s(", sysent[tcp->scno].sys_name);
1745 /*
1746 * " <unavailable>" will be added later by the code which
1747 * detects ptrace errors.
1748 */
1749 goto ret;
1750 }
1751
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001752#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1753 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001754# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001755 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001756 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001757 break;
1758 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001759# endif
1760# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001761 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001762 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001763 break;
1764 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001765# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001766 break;
1767 }
1768#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1769
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001770 if (need_fork_exec_workarounds)
1771 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001772
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001773 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001774 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1775 (tracing_paths && !pathtrace_match(tcp))) {
1776 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1777 return 0;
1778 }
1779
1780 tcp->flags &= ~TCB_FILTERED;
1781
1782 if (cflag == CFLAG_ONLY_STATS) {
1783 res = 0;
1784 goto ret;
1785 }
1786
1787 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001788 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001789 tprintf("syscall_%lu(", tcp->scno);
1790 else
1791 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001792 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001793 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1794 sysent[tcp->scno].sys_func != sys_exit))
1795 res = printargs(tcp);
1796 else
1797 res = (*sysent[tcp->scno].sys_func)(tcp);
1798
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001799 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001800 ret:
1801 tcp->flags |= TCB_INSYSCALL;
1802 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001803 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001804 gettimeofday(&tcp->etime, NULL);
1805 return res;
1806}
1807
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001808/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001809 * 1: ok, continue in trace_syscall_exiting().
1810 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001811 * ("????" etc) and bail out.
1812 */
1813static int
1814get_syscall_result(struct tcb *tcp)
1815{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001816#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001817 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1818 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001819#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001820# define SO_MASK 0x10000000
1821 {
1822 long flags;
1823 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1824 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001825 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001826 return -1;
1827 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001828 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001829 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001830#elif defined(AVR32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001831 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001832#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001833 if (upeek(tcp, PT_R0, &bfin_r0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001834 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001835#elif defined(I386)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001836 /* already done by get_regs */
H.J. Lu35be5812012-04-16 13:00:01 +02001837#elif defined(X86_64) || defined(X32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001838 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001839#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001840# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001841 long psr;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001842 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1843 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001844 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001845 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001846 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001847 return -1;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001848#elif defined(ARM)
1849 /* already done by get_regs */
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001850#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001851 /* register reading already done by get_regs */
1852
1853 /* Used to do this, but we did it on syscall entry already: */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001854 /* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
1855 * else it's personality 0.
1856 */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001857 /*update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));*/
Denys Vlasenko523635f2012-02-25 02:44:25 +01001858#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001859 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001860 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001861#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001862 unsigned long long regs[38];
1863
1864 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1865 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001866 mips_a3 = regs[REG_A3];
1867 mips_r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001868#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001869 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001870 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001871 if (upeek(tcp, REG_V0, &mips_r2) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001872 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001873#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001874 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001875 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001876 if (upeek(tcp, REG_R0, &alpha_r0) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001877 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001878#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001879 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001880#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001881 if (upeek(tcp, PT_GR28, &hppa_r28) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001882 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001883#elif defined(SH)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001884 /* new syscall ABI returns result in R0 */
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001885 if (upeek(tcp, 4*REG_REG0, (long *)&sh_r0) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001886 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001887#elif defined(SH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001888 /* ABI defines result returned in r9 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001889 if (upeek(tcp, REG_GENERAL(9), (long *)&sh64_r9) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001890 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001891#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001892 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001893 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001894#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001895 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001896#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001897 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001898 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001899#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001900 return 1;
1901}
1902
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001903/* Called at each syscall exit */
1904static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001905syscall_fixup_on_sysexit(struct tcb *tcp)
1906{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001907#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001908 if (syscall_mode != -ENOSYS)
1909 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001910 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001911 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1912 /*
1913 * Return from execve.
1914 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1915 * flag set for the post-execve SIGTRAP to see and reset.
1916 */
1917 gpr2 = 0;
1918 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001919#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001920}
1921
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001922/*
1923 * Check the syscall return value register value for whether it is
1924 * a negated errno code indicating an error, or a success return value.
1925 */
1926static inline int
1927is_negated_errno(unsigned long int val)
1928{
1929 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001930#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001931 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001932 val = (unsigned int) val;
1933 max = (unsigned int) max;
1934 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001935#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001936 return val > max;
1937}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001938
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01001939#if defined(X32)
1940static inline int
1941is_negated_errno_x32(unsigned long long val)
1942{
1943 unsigned long long max = -(long long) nerrnos;
1944 /*
1945 * current_wordsize is 4 even in personality 0 (native X32)
1946 * but truncation _must not_ be done in it.
1947 * can't check current_wordsize here!
1948 */
1949 if (current_personality != 0) {
1950 val = (uint32_t) val;
1951 max = (uint32_t) max;
1952 }
1953 return val > max;
1954}
1955#endif
1956
Denys Vlasenko907735a2012-03-21 00:23:16 +01001957/* Returns:
1958 * 1: ok, continue in trace_syscall_exiting().
1959 * -1: error, trace_syscall_exiting() should print error indicator
1960 * ("????" etc) and bail out.
1961 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001962static int
1963get_error(struct tcb *tcp)
1964{
1965 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001966 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001967 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001968 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1969 check_errno = 0;
1970 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001971#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001972 if (check_errno && is_negated_errno(gpr2)) {
1973 tcp->u_rval = -1;
1974 u_error = -gpr2;
1975 }
1976 else {
1977 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001978 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001979#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001980 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001981 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001982 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001983 }
1984 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001985 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001986 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01001987#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001988 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001989 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001990 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001991 }
1992 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001993 tcp->u_rval = x86_64_regs.rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01001994 }
1995#elif defined(X32)
1996 /* Careful: is_negated_errno() works only on longs */
1997 if (check_errno && is_negated_errno_x32(x86_64_regs.rax)) {
1998 tcp->u_rval = -1;
1999 u_error = -x86_64_regs.rax;
2000 }
2001 else {
2002 tcp->u_rval = x86_64_regs.rax; /* truncating */
H.J. Lu35be5812012-04-16 13:00:01 +02002003 tcp->u_lrval = x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002004 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002005#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002006 if (ia32) {
2007 int err;
2008
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002009 err = (int)ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002010 if (check_errno && is_negated_errno(err)) {
2011 tcp->u_rval = -1;
2012 u_error = -err;
2013 }
2014 else {
2015 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002016 }
2017 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002018 if (check_errno && ia64_r10) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002019 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002020 u_error = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002021 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002022 tcp->u_rval = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002023 }
2024 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002025#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002026 if (check_errno && mips_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002027 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002028 u_error = mips_r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002029 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002030 tcp->u_rval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002031# if defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002032 tcp->u_lrval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002033# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002034 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002035#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002036 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002037 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002038 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002039 }
2040 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002041 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002042 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002043#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002044 if (check_errno && is_negated_errno(m68k_d0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002045 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002046 u_error = -m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002047 }
2048 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002049 tcp->u_rval = m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002050 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002051#elif defined(ARM) || defined(AARCH64)
2052# if defined(AARCH64)
2053 if (tcp->currpers == 1) {
2054 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2055 tcp->u_rval = -1;
2056 u_error = -aarch64_regs.regs[0];
2057 }
2058 else {
2059 tcp->u_rval = aarch64_regs.regs[0];
2060 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002061 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002062 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01002063# endif
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002064 {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002065 if (check_errno && is_negated_errno(arm_regs.ARM_r0)) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002066 tcp->u_rval = -1;
Denys Vlasenko401374e2013-02-06 18:24:39 +01002067 u_error = -arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002068 }
2069 else {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002070 tcp->u_rval = arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002071 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002072 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002073#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002074 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
2075 tcp->u_rval = -1;
2076 u_error = -regs.r12;
2077 }
2078 else {
2079 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002080 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002081#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002082 if (check_errno && is_negated_errno(bfin_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002083 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002084 u_error = -bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002085 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002086 tcp->u_rval = bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002087 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002088#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002089 if (check_errno && alpha_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002090 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002091 u_error = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002092 }
2093 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002094 tcp->u_rval = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002095 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002096#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002097 if (check_errno && regs.psr & PSR_C) {
2098 tcp->u_rval = -1;
2099 u_error = regs.u_regs[U_REG_O0];
2100 }
2101 else {
2102 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002103 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002104#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002105 if (check_errno && regs.tstate & 0x1100000000UL) {
2106 tcp->u_rval = -1;
2107 u_error = regs.u_regs[U_REG_O0];
2108 }
2109 else {
2110 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002111 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002112#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002113 if (check_errno && is_negated_errno(hppa_r28)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002114 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002115 u_error = -hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002116 }
2117 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002118 tcp->u_rval = hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002119 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002120#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002121 if (check_errno && is_negated_errno(sh_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002122 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002123 u_error = -sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002124 }
2125 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002126 tcp->u_rval = sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002127 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002128#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002129 if (check_errno && is_negated_errno(sh64_r9)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002130 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002131 u_error = -sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002132 }
2133 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002134 tcp->u_rval = sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002135 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002136#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002137 if (check_errno && cris_r10 && (unsigned) -cris_r10 < nerrnos) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002138 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002139 u_error = -cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002140 }
2141 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002142 tcp->u_rval = cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002143 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002144#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002145 /*
2146 * The standard tile calling convention returns the value (or negative
2147 * errno) in r0, and zero (or positive errno) in r1.
2148 * Until at least kernel 3.8, however, the r1 value is not reflected
2149 * in ptregs at this point, so we use r0 here.
2150 */
2151 if (check_errno && is_negated_errno(tile_regs.regs[0])) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002152 tcp->u_rval = -1;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002153 u_error = -tile_regs.regs[0];
2154 } else {
2155 tcp->u_rval = tile_regs.regs[0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002156 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002157#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002158 if (check_errno && is_negated_errno(microblaze_r3)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002159 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002160 u_error = -microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002161 }
2162 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002163 tcp->u_rval = microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002164 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002165#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002166 tcp->u_error = u_error;
2167 return 1;
2168}
2169
2170static void
2171dumpio(struct tcb *tcp)
2172{
2173 if (syserror(tcp))
2174 return;
2175 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
2176 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002177 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002178 return;
2179 if (sysent[tcp->scno].sys_func == printargs)
2180 return;
2181 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
2182 if (sysent[tcp->scno].sys_func == sys_read ||
2183 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002184 sysent[tcp->scno].sys_func == sys_recv ||
2185 sysent[tcp->scno].sys_func == sys_recvfrom)
2186 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
2187 else if (sysent[tcp->scno].sys_func == sys_readv)
2188 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2189 return;
2190 }
2191 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
2192 if (sysent[tcp->scno].sys_func == sys_write ||
2193 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002194 sysent[tcp->scno].sys_func == sys_send ||
2195 sysent[tcp->scno].sys_func == sys_sendto)
2196 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
2197 else if (sysent[tcp->scno].sys_func == sys_writev)
2198 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2199 return;
2200 }
2201}
2202
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002203static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002204trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002205{
2206 int sys_res;
2207 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002208 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002209 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002210
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002211 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002212 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002213 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002214
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002215#if SUPPORTED_PERSONALITIES > 1
2216 update_personality(tcp, tcp->currpers);
2217#endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002218 res = (get_regs_error ? -1 : get_syscall_result(tcp));
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002219 if (res == 1) {
2220 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01002221 res = get_error(tcp); /* returns 1 or -1 */
2222 if (res == 1) {
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01002223 if (need_fork_exec_workarounds)
2224 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01002225 if (filtered(tcp)) {
2226 goto ret;
2227 }
2228 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002229 }
2230
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002231 if (cflag) {
2232 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002233 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002234 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002235 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002236 }
2237 }
2238
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002239 /* If not in -ff mode, and printing_tcp != tcp,
2240 * then the log currently does not end with output
2241 * of _our syscall entry_, but with something else.
2242 * We need to say which syscall's return is this.
2243 *
2244 * Forced reprinting via TCB_REPRINT is used only by
2245 * "strace -ff -oLOG test/threaded_execve" corner case.
2246 * It's the only case when -ff mode needs reprinting.
2247 */
2248 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2249 tcp->flags &= ~TCB_REPRINT;
2250 printleader(tcp);
2251 if (!SCNO_IN_RANGE(tcp->scno))
2252 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2253 else
2254 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2255 }
2256 printing_tcp = tcp;
2257
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002258 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002259 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002260 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002261 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002262 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002263 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002264 tcp->flags &= ~TCB_INSYSCALL;
2265 return res;
2266 }
2267
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002268 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002269 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002270 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002271 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002272 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002273 /* FIXME: not_failing_only (IOW, option -z) is broken:
2274 * failure of syscall is known only after syscall return.
2275 * Thus we end up with something like this on, say, ENOENT:
2276 * open("doesnt_exist", O_RDONLY <unfinished ...>
2277 * {next syscall decode}
2278 * whereas the intended result is that open(...) line
2279 * is not shown at all.
2280 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002281 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002282 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002283 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2284 }
2285
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002286 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002287 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002288 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002289 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002290 qual_flags[tcp->scno] & QUAL_RAW) {
2291 if (u_error)
2292 tprintf("= -1 (errno %ld)", u_error);
2293 else
2294 tprintf("= %#lx", tcp->u_rval);
2295 }
2296 else if (!(sys_res & RVAL_NONE) && u_error) {
2297 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002298 /* Blocked signals do not interrupt any syscalls.
2299 * In this case syscalls don't return ERESTARTfoo codes.
2300 *
2301 * Deadly signals set to SIG_DFL interrupt syscalls
2302 * and kill the process regardless of which of the codes below
2303 * is returned by the interrupted syscall.
2304 * In some cases, kernel forces a kernel-generated deadly
2305 * signal to be unblocked and set to SIG_DFL (and thus cause
2306 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2307 * or SIGILL. (The alternative is to leave process spinning
2308 * forever on the faulty instruction - not useful).
2309 *
2310 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2311 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2312 * but kernel will always restart them.
2313 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002314 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002315 /* Most common type of signal-interrupted syscall exit code.
2316 * The system call will be restarted with the same arguments
2317 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2318 */
2319 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002320 break;
2321 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002322 /* Rare. For example, fork() returns this if interrupted.
2323 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2324 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002325 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002326 break;
2327 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002328 /* pause(), rt_sigsuspend() etc use this code.
2329 * SA_RESTART is ignored (assumed not set):
2330 * syscall won't restart (will return EINTR instead)
2331 * even after signal with SA_RESTART set.
2332 * However, after SIG_IGN or SIG_DFL signal it will.
2333 */
2334 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002335 break;
2336 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002337 /* Syscalls like nanosleep(), poll() which can't be
2338 * restarted with their original arguments use this
2339 * code. Kernel will execute restart_syscall() instead,
2340 * which changes arguments before restarting syscall.
2341 * SA_RESTART is ignored (assumed not set) similarly
2342 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2343 * since restart data is saved in "restart block"
2344 * in task struct, and if signal handler uses a syscall
2345 * which in turn saves another such restart block,
2346 * old data is lost and restart becomes impossible)
2347 */
2348 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002349 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002350 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002351 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002352 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002353 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002354 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002355 strerror(u_error));
2356 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002357 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002358 strerror(u_error));
2359 break;
2360 }
2361 if ((sys_res & RVAL_STR) && tcp->auxstr)
2362 tprintf(" (%s)", tcp->auxstr);
2363 }
2364 else {
2365 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002366 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002367 else {
2368 switch (sys_res & RVAL_MASK) {
2369 case RVAL_HEX:
2370 tprintf("= %#lx", tcp->u_rval);
2371 break;
2372 case RVAL_OCTAL:
2373 tprintf("= %#lo", tcp->u_rval);
2374 break;
2375 case RVAL_UDECIMAL:
2376 tprintf("= %lu", tcp->u_rval);
2377 break;
2378 case RVAL_DECIMAL:
2379 tprintf("= %ld", tcp->u_rval);
2380 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002381#if defined(LINUX_MIPSN32) || defined(X32)
2382 /*
2383 case RVAL_LHEX:
2384 tprintf("= %#llx", tcp->u_lrval);
2385 break;
2386 case RVAL_LOCTAL:
2387 tprintf("= %#llo", tcp->u_lrval);
2388 break;
2389 */
2390 case RVAL_LUDECIMAL:
2391 tprintf("= %llu", tcp->u_lrval);
2392 break;
2393 /*
2394 case RVAL_LDECIMAL:
2395 tprintf("= %lld", tcp->u_lrval);
2396 break;
2397 */
2398#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002399 default:
2400 fprintf(stderr,
2401 "invalid rval format\n");
2402 break;
2403 }
2404 }
2405 if ((sys_res & RVAL_STR) && tcp->auxstr)
2406 tprintf(" (%s)", tcp->auxstr);
2407 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002408 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002409 tv_sub(&tv, &tv, &tcp->etime);
2410 tprintf(" <%ld.%06ld>",
2411 (long) tv.tv_sec, (long) tv.tv_usec);
2412 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002413 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002414 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002415 line_ended();
2416
Denys Vlasenko3b738812011-08-22 02:06:35 +02002417 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002418 tcp->flags &= ~TCB_INSYSCALL;
2419 return 0;
2420}
2421
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002422int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002423trace_syscall(struct tcb *tcp)
2424{
2425 return exiting(tcp) ?
2426 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2427}