blob: f403c44187af6f48969f3fb3bd2f56153992a08a [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 Vlasenkob63256e2011-06-07 12:13:24 +0200674static long 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 Vlasenkob63256e2011-06-07 12:13:24 +0200688static long 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 Vlasenkob63256e2011-06-07 12:13:24 +0200695static long long a3;
696static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100697#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200698static long a3;
699static long 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 Vlasenkob63256e2011-06-07 12:13:24 +0200706static long 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;
1176 a3 = regs[REG_A3];
1177 r2 = regs[REG_V0];
1178
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001179 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001180 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001181 if (a3 == 0 || 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 Vlasenko932fc7d2008-12-16 18:18:40 +00001188 if (upeek(tcp, REG_A3, &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 Vlasenko8cd1acd2011-08-24 16:52:57 +02001194 if (a3 == 0 || 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 Vlasenko523635f2012-02-25 02:44:25 +01001333#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001334 /* new syscall ABI returns result in R0 */
1335 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1336 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001337#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001338 /* ABI defines result returned in r9 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001339 if (upeek(tcp, REG_GENERAL(9), (long *)&sh64_r9) < 0)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001340 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001341#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001342
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001343 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001344 return 1;
1345}
1346
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001347/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001348 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001349 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1350 * 1: ok, continue in trace_syscall_entering().
1351 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001352 * ("????" etc) and bail out.
1353 */
Roland McGratha4d48532005-06-08 20:45:28 +00001354static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001355syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001356{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001357 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001358#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001359 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001360 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001361 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1362 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001363 }
H.J. Lu35be5812012-04-16 13:00:01 +02001364#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001365 {
1366 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001367 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001368 rax = (int)rax; /* sign extend from 32 bits */
1369 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001370 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001371 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1372 return 0;
1373 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001374 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001375#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001376 /* TODO: we already fetched PT_GPR2 in get_scno
1377 * and stored it in syscall_mode, reuse it here
1378 * instead of re-fetching?
1379 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001380 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001381 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001382 if (syscall_mode != -ENOSYS)
1383 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001384 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001385 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001386 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001387 return 0;
1388 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001389#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001390 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001391 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001392 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001393 if (m68k_d0 != -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 (d0 = %ld)\n", m68k_d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001396 return 0;
1397 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001398#elif defined(IA64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001399 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001400 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001401 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001402 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001403 if (ia32 && ia64_r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001404 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001405 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", ia64_r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001406 return 0;
1407 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001408#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001409 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001410 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001411 if (cris_r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001412 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001413 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", cris_r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001414 return 0;
1415 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001416#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001417 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001418 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001419 if (microblaze_r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001420 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001421 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", microblaze_r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001422 return 0;
1423 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001424#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001425 return 1;
1426}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001427
Denys Vlasenko146b9442012-03-18 22:10:48 +01001428static void
1429internal_fork(struct tcb *tcp)
1430{
1431#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1432# define ARG_FLAGS 1
1433#else
1434# define ARG_FLAGS 0
1435#endif
1436#ifndef CLONE_UNTRACED
1437# define CLONE_UNTRACED 0x00800000
1438#endif
1439 if ((ptrace_setoptions
1440 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1441 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1442 return;
1443
1444 if (!followfork)
1445 return;
1446
1447 if (entering(tcp)) {
1448 /*
1449 * We won't see the new child if clone is called with
1450 * CLONE_UNTRACED, so we keep the same logic with that option
1451 * and don't trace it.
1452 */
1453 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1454 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1455 return;
1456 setbpt(tcp);
1457 } else {
1458 if (tcp->flags & TCB_BPTSET)
1459 clearbpt(tcp);
1460 }
1461}
1462
1463#if defined(TCB_WAITEXECVE)
1464static void
1465internal_exec(struct tcb *tcp)
1466{
1467 /* Maybe we have post-execve SIGTRAP suppressed? */
1468 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1469 return; /* yes, no need to do anything */
1470
1471 if (exiting(tcp) && syserror(tcp))
1472 /* Error in execve, no post-execve SIGTRAP expected */
1473 tcp->flags &= ~TCB_WAITEXECVE;
1474 else
1475 tcp->flags |= TCB_WAITEXECVE;
1476}
1477#endif
1478
1479static void
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001480syscall_fixup_for_fork_exec(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001481{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001482 /*
1483 * We must always trace a few critical system calls in order to
1484 * correctly support following forks in the presence of tracing
1485 * qualifiers.
1486 */
1487 int (*func)();
1488
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001489 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001490 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001491
1492 func = sysent[tcp->scno].sys_func;
1493
1494 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001495 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001496 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001497 ) {
1498 internal_fork(tcp);
1499 return;
1500 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001501
Denys Vlasenko84703742012-02-25 02:38:52 +01001502#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001503 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001504# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001505 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001506# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001507 ) {
1508 internal_exec(tcp);
1509 return;
1510 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001511#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001512}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001513
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001514/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001515static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001516get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001517{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001518 int i, nargs;
1519
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001520 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001521 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001522 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001523 nargs = tcp->u_nargs = MAX_ARGS;
1524
Denys Vlasenko523635f2012-02-25 02:44:25 +01001525#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001526 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001527 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1528 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001529#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001530 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001531 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1532 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001533#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001534 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001535 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001536 long rbs_end;
1537 /* be backwards compatible with kernel < 2.4.4... */
1538# ifndef PT_RBS_END
1539# define PT_RBS_END PT_AR_BSP
1540# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001541
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001542 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1543 return -1;
1544 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001545 return -1;
1546
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001547 sof = (cfm >> 0) & 0x7f;
1548 sol = (cfm >> 7) & 0x7f;
1549 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1550
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001551 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001552 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1553 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1554 return -1;
1555 }
1556 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001557 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1558 PT_R9 /* ECX = out1 */,
1559 PT_R10 /* EDX = out2 */,
1560 PT_R14 /* ESI = out3 */,
1561 PT_R15 /* EDI = out4 */,
1562 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001563
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001564 for (i = 0; i < nargs; ++i) {
1565 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1566 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001567 /* truncate away IVE sign-extension */
1568 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001569 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001570 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001571#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001572 /* N32 and N64 both use up to six registers. */
1573 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001574
1575 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1576 return -1;
1577
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001578 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001579 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001580# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001581 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001582# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001583 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001584#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001585 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001586 long sp;
1587
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001588 if (upeek(tcp, REG_SP, &sp) < 0)
1589 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001590 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001591 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1592 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001593 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001594 (char *)(tcp->u_arg + 4));
1595 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001596 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001597 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001598 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001599 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001600#elif defined(POWERPC)
1601# ifndef PT_ORIG_R3
1602# define PT_ORIG_R3 34
1603# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001604 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001605 if (upeek(tcp, (i==0) ?
1606 (sizeof(unsigned long) * PT_ORIG_R3) :
1607 ((i+PT_R3) * sizeof(unsigned long)),
1608 &tcp->u_arg[i]) < 0)
1609 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001610 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001611#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001612 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001613 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001614#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001615 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001616 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1617 return -1;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001618#elif defined(ARM) || defined(AARCH64)
1619# if defined(AARCH64)
1620 if (tcp->currpers == 1)
1621 for (i = 0; i < nargs; ++i)
1622 tcp->u_arg[i] = aarch64_regs.regs[i];
1623 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001624# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001625 for (i = 0; i < nargs; ++i)
Denys Vlasenko401374e2013-02-06 18:24:39 +01001626 tcp->u_arg[i] = arm_regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001627#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001628 (void)i;
1629 (void)nargs;
1630 tcp->u_arg[0] = regs.r12;
1631 tcp->u_arg[1] = regs.r11;
1632 tcp->u_arg[2] = regs.r10;
1633 tcp->u_arg[3] = regs.r9;
1634 tcp->u_arg[4] = regs.r5;
1635 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001636#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001637 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 +02001638
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001639 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001640 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1641 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001642#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001643 static const int syscall_regs[MAX_ARGS] = {
1644 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1645 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001646 };
1647
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001648 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001649 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001650 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001651#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001652 int i;
1653 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001654 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001655
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001656 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001657 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1658 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001659#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001660 (void)i;
1661 (void)nargs;
H.J. Lu35be5812012-04-16 13:00:01 +02001662 if (current_personality != 1) { /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001663 tcp->u_arg[0] = x86_64_regs.rdi;
1664 tcp->u_arg[1] = x86_64_regs.rsi;
1665 tcp->u_arg[2] = x86_64_regs.rdx;
1666 tcp->u_arg[3] = x86_64_regs.r10;
1667 tcp->u_arg[4] = x86_64_regs.r8;
1668 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001669# ifdef X32
1670 tcp->ext_arg[0] = x86_64_regs.rdi;
1671 tcp->ext_arg[1] = x86_64_regs.rsi;
1672 tcp->ext_arg[2] = x86_64_regs.rdx;
1673 tcp->ext_arg[3] = x86_64_regs.r10;
1674 tcp->ext_arg[4] = x86_64_regs.r8;
1675 tcp->ext_arg[5] = x86_64_regs.r9;
1676# endif
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001677 } else { /* i386 ABI */
1678 /* Sign-extend lower 32 bits */
1679 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1680 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1681 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1682 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1683 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1684 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1685 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001686#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001687 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001688 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1689 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001690#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001691 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001692 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001693 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001694 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001695
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001696 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001697 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1698 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001699#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001700 for (i = 0; i < nargs; ++i)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001701 tcp->u_arg[i] = tile_regs.regs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001702#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001703 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001704 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1705 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001706#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001707 (void)i;
1708 (void)nargs;
1709 tcp->u_arg[0] = i386_regs.ebx;
1710 tcp->u_arg[1] = i386_regs.ecx;
1711 tcp->u_arg[2] = i386_regs.edx;
1712 tcp->u_arg[3] = i386_regs.esi;
1713 tcp->u_arg[4] = i386_regs.edi;
1714 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001715#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001716 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001717 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1718 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001719#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001720 return 1;
1721}
1722
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001723static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001724trace_syscall_entering(struct tcb *tcp)
1725{
1726 int res, scno_good;
1727
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001728#if defined TCB_WAITEXECVE
1729 if (tcp->flags & TCB_WAITEXECVE) {
1730 /* This is the post-execve SIGTRAP. */
1731 tcp->flags &= ~TCB_WAITEXECVE;
1732 return 0;
1733 }
1734#endif
1735
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001736 scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001737 if (res == 0)
1738 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001739 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001740 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001741 if (res == 0)
1742 return res;
1743 if (res == 1)
1744 res = get_syscall_args(tcp);
1745 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001746
1747 if (res != 1) {
1748 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001749 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001750 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001751 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001752 tprintf("syscall_%lu(", tcp->scno);
1753 else
1754 tprintf("%s(", sysent[tcp->scno].sys_name);
1755 /*
1756 * " <unavailable>" will be added later by the code which
1757 * detects ptrace errors.
1758 */
1759 goto ret;
1760 }
1761
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001762#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1763 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001764# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001765 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001766 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001767 break;
1768 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001769# endif
1770# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001771 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001772 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001773 break;
1774 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001775# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001776 break;
1777 }
1778#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1779
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001780 if (need_fork_exec_workarounds)
1781 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001782
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001783 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001784 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1785 (tracing_paths && !pathtrace_match(tcp))) {
1786 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1787 return 0;
1788 }
1789
1790 tcp->flags &= ~TCB_FILTERED;
1791
1792 if (cflag == CFLAG_ONLY_STATS) {
1793 res = 0;
1794 goto ret;
1795 }
1796
1797 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001798 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001799 tprintf("syscall_%lu(", tcp->scno);
1800 else
1801 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001802 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001803 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1804 sysent[tcp->scno].sys_func != sys_exit))
1805 res = printargs(tcp);
1806 else
1807 res = (*sysent[tcp->scno].sys_func)(tcp);
1808
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001809 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001810 ret:
1811 tcp->flags |= TCB_INSYSCALL;
1812 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001813 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001814 gettimeofday(&tcp->etime, NULL);
1815 return res;
1816}
1817
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001818/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001819 * 1: ok, continue in trace_syscall_exiting().
1820 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001821 * ("????" etc) and bail out.
1822 */
1823static int
1824get_syscall_result(struct tcb *tcp)
1825{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001826#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001827 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1828 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001829#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001830# define SO_MASK 0x10000000
1831 {
1832 long flags;
1833 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1834 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001835 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001836 return -1;
1837 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001838 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001839 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001840#elif defined(AVR32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001841 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001842#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001843 if (upeek(tcp, PT_R0, &r0) < 0)
1844 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001845#elif defined(I386)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001846 /* already done by get_regs */
H.J. Lu35be5812012-04-16 13:00:01 +02001847#elif defined(X86_64) || defined(X32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001848 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001849#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001850# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001851 long psr;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001852 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1853 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001854 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001855 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001856 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001857 return -1;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001858#elif defined(ARM)
1859 /* already done by get_regs */
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001860#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001861 /* register reading already done by get_regs */
1862
1863 /* Used to do this, but we did it on syscall entry already: */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001864 /* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
1865 * else it's personality 0.
1866 */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001867 /*update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));*/
Denys Vlasenko523635f2012-02-25 02:44:25 +01001868#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001869 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001870 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001871#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001872 unsigned long long regs[38];
1873
1874 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1875 return -1;
1876 a3 = regs[REG_A3];
1877 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001878#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001879 if (upeek(tcp, REG_A3, &a3) < 0)
1880 return -1;
1881 if (upeek(tcp, REG_V0, &r2) < 0)
1882 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001883#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001884 if (upeek(tcp, REG_A3, &a3) < 0)
1885 return -1;
1886 if (upeek(tcp, REG_R0, &r0) < 0)
1887 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001888#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001889 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001890#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001891 if (upeek(tcp, PT_GR28, &hppa_r28) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001892 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001893#elif defined(SH)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001894 /* new syscall ABI returns result in R0 */
1895 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1896 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001897#elif defined(SH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001898 /* ABI defines result returned in r9 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001899 if (upeek(tcp, REG_GENERAL(9), (long *)&sh64_r9) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001900 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001901#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001902 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001903 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001904#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001905 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001906#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001907 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001908 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001909#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001910 return 1;
1911}
1912
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001913/* Called at each syscall exit */
1914static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001915syscall_fixup_on_sysexit(struct tcb *tcp)
1916{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001917#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001918 if (syscall_mode != -ENOSYS)
1919 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001920 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001921 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1922 /*
1923 * Return from execve.
1924 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1925 * flag set for the post-execve SIGTRAP to see and reset.
1926 */
1927 gpr2 = 0;
1928 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001929#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001930}
1931
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001932/*
1933 * Check the syscall return value register value for whether it is
1934 * a negated errno code indicating an error, or a success return value.
1935 */
1936static inline int
1937is_negated_errno(unsigned long int val)
1938{
1939 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001940#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001941 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001942 val = (unsigned int) val;
1943 max = (unsigned int) max;
1944 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001945#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001946 return val > max;
1947}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001948
Denys Vlasenko907735a2012-03-21 00:23:16 +01001949/* Returns:
1950 * 1: ok, continue in trace_syscall_exiting().
1951 * -1: error, trace_syscall_exiting() should print error indicator
1952 * ("????" etc) and bail out.
1953 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001954static int
1955get_error(struct tcb *tcp)
1956{
1957 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001958 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001959 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001960 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1961 check_errno = 0;
1962 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001963#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001964 if (check_errno && is_negated_errno(gpr2)) {
1965 tcp->u_rval = -1;
1966 u_error = -gpr2;
1967 }
1968 else {
1969 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001970 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001971#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001972 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001973 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001974 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001975 }
1976 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001977 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001978 }
H.J. Lu35be5812012-04-16 13:00:01 +02001979#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001980 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001981 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001982 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001983 }
1984 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001985 tcp->u_rval = x86_64_regs.rax;
H.J. Lu35be5812012-04-16 13:00:01 +02001986# if defined(X32)
1987 tcp->u_lrval = x86_64_regs.rax;
1988# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001989 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001990#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001991 if (ia32) {
1992 int err;
1993
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001994 err = (int)ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001995 if (check_errno && is_negated_errno(err)) {
1996 tcp->u_rval = -1;
1997 u_error = -err;
1998 }
1999 else {
2000 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002001 }
2002 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002003 if (check_errno && ia64_r10) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002004 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002005 u_error = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002006 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002007 tcp->u_rval = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002008 }
2009 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002010#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002011 if (check_errno && a3) {
2012 tcp->u_rval = -1;
2013 u_error = r2;
2014 } else {
2015 tcp->u_rval = r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002016# if defined(LINUX_MIPSN32)
2017 tcp->u_lrval = r2;
2018# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002019 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002020#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002021 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002022 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002023 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002024 }
2025 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002026 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002027 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002028#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002029 if (check_errno && is_negated_errno(m68k_d0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002030 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002031 u_error = -m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002032 }
2033 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002034 tcp->u_rval = m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002035 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002036#elif defined(ARM) || defined(AARCH64)
2037# if defined(AARCH64)
2038 if (tcp->currpers == 1) {
2039 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2040 tcp->u_rval = -1;
2041 u_error = -aarch64_regs.regs[0];
2042 }
2043 else {
2044 tcp->u_rval = aarch64_regs.regs[0];
2045 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002046 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002047 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01002048# endif
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002049 {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002050 if (check_errno && is_negated_errno(arm_regs.ARM_r0)) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002051 tcp->u_rval = -1;
Denys Vlasenko401374e2013-02-06 18:24:39 +01002052 u_error = -arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002053 }
2054 else {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002055 tcp->u_rval = arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002056 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002057 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002058#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002059 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
2060 tcp->u_rval = -1;
2061 u_error = -regs.r12;
2062 }
2063 else {
2064 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002065 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002066#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002067 if (check_errno && is_negated_errno(r0)) {
2068 tcp->u_rval = -1;
2069 u_error = -r0;
2070 } else {
2071 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002072 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002073#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002074 if (check_errno && alpha_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002075 tcp->u_rval = -1;
2076 u_error = r0;
2077 }
2078 else {
2079 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002080 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002081#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002082 if (check_errno && regs.psr & PSR_C) {
2083 tcp->u_rval = -1;
2084 u_error = regs.u_regs[U_REG_O0];
2085 }
2086 else {
2087 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002088 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002089#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002090 if (check_errno && regs.tstate & 0x1100000000UL) {
2091 tcp->u_rval = -1;
2092 u_error = regs.u_regs[U_REG_O0];
2093 }
2094 else {
2095 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002096 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002097#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002098 if (check_errno && is_negated_errno(hppa_r28)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002099 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002100 u_error = -hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002101 }
2102 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002103 tcp->u_rval = hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002104 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002105#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002106 if (check_errno && is_negated_errno(r0)) {
2107 tcp->u_rval = -1;
2108 u_error = -r0;
2109 }
2110 else {
2111 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002112 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002113#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002114 if (check_errno && is_negated_errno(sh64_r9)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002115 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002116 u_error = -sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002117 }
2118 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002119 tcp->u_rval = sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002120 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002121#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002122 if (check_errno && cris_r10 && (unsigned) -cris_r10 < nerrnos) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002123 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002124 u_error = -cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002125 }
2126 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002127 tcp->u_rval = cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002128 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002129#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002130 /*
2131 * The standard tile calling convention returns the value (or negative
2132 * errno) in r0, and zero (or positive errno) in r1.
2133 * Until at least kernel 3.8, however, the r1 value is not reflected
2134 * in ptregs at this point, so we use r0 here.
2135 */
2136 if (check_errno && is_negated_errno(tile_regs.regs[0])) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002137 tcp->u_rval = -1;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002138 u_error = -tile_regs.regs[0];
2139 } else {
2140 tcp->u_rval = tile_regs.regs[0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002141 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002142#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002143 if (check_errno && is_negated_errno(microblaze_r3)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002144 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002145 u_error = -microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002146 }
2147 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002148 tcp->u_rval = microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002149 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002150#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002151 tcp->u_error = u_error;
2152 return 1;
2153}
2154
2155static void
2156dumpio(struct tcb *tcp)
2157{
2158 if (syserror(tcp))
2159 return;
2160 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
2161 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002162 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002163 return;
2164 if (sysent[tcp->scno].sys_func == printargs)
2165 return;
2166 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
2167 if (sysent[tcp->scno].sys_func == sys_read ||
2168 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002169 sysent[tcp->scno].sys_func == sys_recv ||
2170 sysent[tcp->scno].sys_func == sys_recvfrom)
2171 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
2172 else if (sysent[tcp->scno].sys_func == sys_readv)
2173 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2174 return;
2175 }
2176 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
2177 if (sysent[tcp->scno].sys_func == sys_write ||
2178 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002179 sysent[tcp->scno].sys_func == sys_send ||
2180 sysent[tcp->scno].sys_func == sys_sendto)
2181 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
2182 else if (sysent[tcp->scno].sys_func == sys_writev)
2183 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2184 return;
2185 }
2186}
2187
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002188static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002189trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002190{
2191 int sys_res;
2192 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002193 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002194 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002195
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002196 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002197 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002198 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002199
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002200#if SUPPORTED_PERSONALITIES > 1
2201 update_personality(tcp, tcp->currpers);
2202#endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002203 res = (get_regs_error ? -1 : get_syscall_result(tcp));
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002204 if (res == 1) {
2205 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01002206 res = get_error(tcp); /* returns 1 or -1 */
2207 if (res == 1) {
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01002208 if (need_fork_exec_workarounds)
2209 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01002210 if (filtered(tcp)) {
2211 goto ret;
2212 }
2213 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002214 }
2215
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002216 if (cflag) {
2217 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002218 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002219 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002220 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002221 }
2222 }
2223
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002224 /* If not in -ff mode, and printing_tcp != tcp,
2225 * then the log currently does not end with output
2226 * of _our syscall entry_, but with something else.
2227 * We need to say which syscall's return is this.
2228 *
2229 * Forced reprinting via TCB_REPRINT is used only by
2230 * "strace -ff -oLOG test/threaded_execve" corner case.
2231 * It's the only case when -ff mode needs reprinting.
2232 */
2233 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2234 tcp->flags &= ~TCB_REPRINT;
2235 printleader(tcp);
2236 if (!SCNO_IN_RANGE(tcp->scno))
2237 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2238 else
2239 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2240 }
2241 printing_tcp = tcp;
2242
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002243 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002244 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002245 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002246 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002247 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002248 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002249 tcp->flags &= ~TCB_INSYSCALL;
2250 return res;
2251 }
2252
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002253 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002254 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002255 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002256 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002257 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002258 /* FIXME: not_failing_only (IOW, option -z) is broken:
2259 * failure of syscall is known only after syscall return.
2260 * Thus we end up with something like this on, say, ENOENT:
2261 * open("doesnt_exist", O_RDONLY <unfinished ...>
2262 * {next syscall decode}
2263 * whereas the intended result is that open(...) line
2264 * is not shown at all.
2265 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002266 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002267 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002268 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2269 }
2270
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002271 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002272 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002273 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002274 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002275 qual_flags[tcp->scno] & QUAL_RAW) {
2276 if (u_error)
2277 tprintf("= -1 (errno %ld)", u_error);
2278 else
2279 tprintf("= %#lx", tcp->u_rval);
2280 }
2281 else if (!(sys_res & RVAL_NONE) && u_error) {
2282 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002283 /* Blocked signals do not interrupt any syscalls.
2284 * In this case syscalls don't return ERESTARTfoo codes.
2285 *
2286 * Deadly signals set to SIG_DFL interrupt syscalls
2287 * and kill the process regardless of which of the codes below
2288 * is returned by the interrupted syscall.
2289 * In some cases, kernel forces a kernel-generated deadly
2290 * signal to be unblocked and set to SIG_DFL (and thus cause
2291 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2292 * or SIGILL. (The alternative is to leave process spinning
2293 * forever on the faulty instruction - not useful).
2294 *
2295 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2296 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2297 * but kernel will always restart them.
2298 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002299 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002300 /* Most common type of signal-interrupted syscall exit code.
2301 * The system call will be restarted with the same arguments
2302 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2303 */
2304 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002305 break;
2306 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002307 /* Rare. For example, fork() returns this if interrupted.
2308 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2309 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002310 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002311 break;
2312 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002313 /* pause(), rt_sigsuspend() etc use this code.
2314 * SA_RESTART is ignored (assumed not set):
2315 * syscall won't restart (will return EINTR instead)
2316 * even after signal with SA_RESTART set.
2317 * However, after SIG_IGN or SIG_DFL signal it will.
2318 */
2319 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002320 break;
2321 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002322 /* Syscalls like nanosleep(), poll() which can't be
2323 * restarted with their original arguments use this
2324 * code. Kernel will execute restart_syscall() instead,
2325 * which changes arguments before restarting syscall.
2326 * SA_RESTART is ignored (assumed not set) similarly
2327 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2328 * since restart data is saved in "restart block"
2329 * in task struct, and if signal handler uses a syscall
2330 * which in turn saves another such restart block,
2331 * old data is lost and restart becomes impossible)
2332 */
2333 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002334 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002335 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002336 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002337 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002338 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002339 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002340 strerror(u_error));
2341 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002342 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002343 strerror(u_error));
2344 break;
2345 }
2346 if ((sys_res & RVAL_STR) && tcp->auxstr)
2347 tprintf(" (%s)", tcp->auxstr);
2348 }
2349 else {
2350 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002351 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002352 else {
2353 switch (sys_res & RVAL_MASK) {
2354 case RVAL_HEX:
2355 tprintf("= %#lx", tcp->u_rval);
2356 break;
2357 case RVAL_OCTAL:
2358 tprintf("= %#lo", tcp->u_rval);
2359 break;
2360 case RVAL_UDECIMAL:
2361 tprintf("= %lu", tcp->u_rval);
2362 break;
2363 case RVAL_DECIMAL:
2364 tprintf("= %ld", tcp->u_rval);
2365 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002366#if defined(LINUX_MIPSN32) || defined(X32)
2367 /*
2368 case RVAL_LHEX:
2369 tprintf("= %#llx", tcp->u_lrval);
2370 break;
2371 case RVAL_LOCTAL:
2372 tprintf("= %#llo", tcp->u_lrval);
2373 break;
2374 */
2375 case RVAL_LUDECIMAL:
2376 tprintf("= %llu", tcp->u_lrval);
2377 break;
2378 /*
2379 case RVAL_LDECIMAL:
2380 tprintf("= %lld", tcp->u_lrval);
2381 break;
2382 */
2383#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002384 default:
2385 fprintf(stderr,
2386 "invalid rval format\n");
2387 break;
2388 }
2389 }
2390 if ((sys_res & RVAL_STR) && tcp->auxstr)
2391 tprintf(" (%s)", tcp->auxstr);
2392 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002393 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002394 tv_sub(&tv, &tv, &tcp->etime);
2395 tprintf(" <%ld.%06ld>",
2396 (long) tv.tv_sec, (long) tv.tv_usec);
2397 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002398 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002399 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002400 line_ended();
2401
Denys Vlasenko3b738812011-08-22 02:06:35 +02002402 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002403 tcp->flags &= ~TCB_INSYSCALL;
2404 return 0;
2405}
2406
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002407int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002408trace_syscall(struct tcb *tcp)
2409{
2410 return exiting(tcp) ?
2411 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2412}