blob: a73651de188fa6fa7f0c47f50cc7f04661a3ad5f [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
Chris Metcalf0b99a8a2013-02-05 17:48:33 +010074#if defined(TILE)
75# ifndef PT_FLAGS_COMPAT
76# define PT_FLAGS_COMPAT 0x10000 /* from Linux 3.8 on */
77# endif
78#endif
79
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000080#ifndef ERESTARTSYS
Denys Vlasenko523635f2012-02-25 02:44:25 +010081# define ERESTARTSYS 512
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000082#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010083#ifndef ERESTARTNOINTR
Denys Vlasenko523635f2012-02-25 02:44:25 +010084# define ERESTARTNOINTR 513
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000085#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010086#ifndef ERESTARTNOHAND
87# define ERESTARTNOHAND 514 /* restart if no handler */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000088#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010089#ifndef ERESTART_RESTARTBLOCK
Denys Vlasenko523635f2012-02-25 02:44:25 +010090# define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
Roland McGrath9c555e72003-07-09 09:47:59 +000091#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010092
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000093#ifndef NSIG
Denys Vlasenko523635f2012-02-25 02:44:25 +010094# warning: NSIG is not defined, using 32
95# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000096#endif
97#ifdef ARM
Denys Vlasenko041b3ee2011-08-18 12:48:56 +020098/* Ugh. Is this really correct? ARM has no RT signals?! */
Denys Vlasenko523635f2012-02-25 02:44:25 +010099# undef NSIG
100# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000101#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102
103#include "syscall.h"
104
105/* Define these shorthand notations to simplify the syscallent files. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000106#define TD TRACE_DESC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000107#define TF TRACE_FILE
108#define TI TRACE_IPC
109#define TN TRACE_NETWORK
110#define TP TRACE_PROCESS
111#define TS TRACE_SIGNAL
Namhyung Kim96792962012-10-24 11:41:57 +0900112#define TM TRACE_MEMORY
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000113#define NF SYSCALL_NEVER_FAILS
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200114#define MA MAX_ARGS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000115
Roland McGrathee36ce12004-09-04 03:53:10 +0000116static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000117#include "syscallent.h"
118};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000119
120#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000121static const struct sysent sysent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100122# include "syscallent1.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#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000127static const struct sysent sysent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100128# include "syscallent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000129};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200130#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000131
132/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000133#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000134#undef TF
135#undef TI
136#undef TN
137#undef TP
138#undef TS
Namhyung Kim96792962012-10-24 11:41:57 +0900139#undef TM
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000140#undef NF
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200141#undef MA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142
Denys Vlasenko39fca622011-08-20 02:12:33 +0200143/*
144 * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
145 * program `ioctlsort', such that the list is sorted by the `code' field.
146 * This has the side-effect of resolving the _IO.. macros into
147 * plain integers, eliminating the need to include here everything
148 * in "/usr/include".
149 */
150
Roland McGrathee36ce12004-09-04 03:53:10 +0000151static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000152#include "errnoent.h"
153};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200154static const char *const signalent0[] = {
155#include "signalent.h"
156};
157static const struct ioctlent ioctlent0[] = {
158#include "ioctlent.h"
159};
160enum { nsyscalls0 = ARRAY_SIZE(sysent0) };
161enum { nerrnos0 = ARRAY_SIZE(errnoent0) };
162enum { nsignals0 = ARRAY_SIZE(signalent0) };
163enum { nioctlents0 = ARRAY_SIZE(ioctlent0) };
164int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000165
166#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000167static const char *const errnoent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100168# include "errnoent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000169};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200170static const char *const signalent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100171# include "signalent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200172};
173static const struct ioctlent ioctlent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100174# include "ioctlent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200175};
176enum { nsyscalls1 = ARRAY_SIZE(sysent1) };
177enum { nerrnos1 = ARRAY_SIZE(errnoent1) };
178enum { nsignals1 = ARRAY_SIZE(signalent1) };
179enum { nioctlents1 = ARRAY_SIZE(ioctlent1) };
180int qual_flags1[MAX_QUALS];
181#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000182
183#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000184static const char *const errnoent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100185# include "errnoent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000186};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200187static const char *const signalent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100188# include "signalent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200189};
190static const struct ioctlent ioctlent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100191# include "ioctlent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200192};
193enum { nsyscalls2 = ARRAY_SIZE(sysent2) };
194enum { nerrnos2 = ARRAY_SIZE(errnoent2) };
195enum { nsignals2 = ARRAY_SIZE(signalent2) };
196enum { nioctlents2 = ARRAY_SIZE(ioctlent2) };
197int qual_flags2[MAX_QUALS];
198#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000199
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100200const struct sysent *sysent = sysent0;
201const char *const *errnoent = errnoent0;
202const char *const *signalent = signalent0;
203const struct ioctlent *ioctlent = ioctlent0;
204unsigned nsyscalls = nsyscalls0;
205unsigned nerrnos = nerrnos0;
206unsigned nsignals = nsignals0;
207unsigned nioctlents = nioctlents0;
208int *qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000209
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100210#if SUPPORTED_PERSONALITIES > 1
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000211int current_personality;
212
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000213const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
214 PERSONALITY0_WORDSIZE,
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000215 PERSONALITY1_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100216# if SUPPORTED_PERSONALITIES > 2
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000217 PERSONALITY2_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100218# endif
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200219};
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000220
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200221void
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000222set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000223{
224 switch (personality) {
225 case 0:
226 errnoent = errnoent0;
227 nerrnos = nerrnos0;
228 sysent = sysent0;
229 nsyscalls = nsyscalls0;
230 ioctlent = ioctlent0;
231 nioctlents = nioctlents0;
232 signalent = signalent0;
233 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000234 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000235 break;
236
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000237 case 1:
238 errnoent = errnoent1;
239 nerrnos = nerrnos1;
240 sysent = sysent1;
241 nsyscalls = nsyscalls1;
242 ioctlent = ioctlent1;
243 nioctlents = nioctlents1;
244 signalent = signalent1;
245 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000246 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000247 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000248
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100249# if SUPPORTED_PERSONALITIES >= 3
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000250 case 2:
251 errnoent = errnoent2;
252 nerrnos = nerrnos2;
253 sysent = sysent2;
254 nsyscalls = nsyscalls2;
255 ioctlent = ioctlent2;
256 nioctlents = nioctlents2;
257 signalent = signalent2;
258 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000259 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000260 break;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100261# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000262 }
263
264 current_personality = personality;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000265}
266
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000267static void
268update_personality(struct tcb *tcp, int personality)
269{
270 if (personality == current_personality)
271 return;
272 set_personality(personality);
273
274 if (personality == tcp->currpers)
275 return;
276 tcp->currpers = personality;
277
H.J. Lu35be5812012-04-16 13:00:01 +0200278# if defined(POWERPC64)
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000279 if (!qflag) {
280 static const char *const names[] = {"64 bit", "32 bit"};
281 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
282 tcp->pid, names[personality]);
283 }
H.J. Lu35be5812012-04-16 13:00:01 +0200284# elif defined(X86_64)
285 if (!qflag) {
286 static const char *const names[] = {"64 bit", "32 bit", "x32"};
287 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
288 tcp->pid, names[personality]);
289 }
H.J. Lu085e4282012-04-17 11:05:04 -0700290# elif defined(X32)
291 if (!qflag) {
292 static const char *const names[] = {"x32", "32 bit"};
293 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
294 tcp->pid, names[personality]);
295 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000296# elif defined(AARCH64)
297 if (!qflag) {
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100298 static const char *const names[] = {"32-bit", "AArch64"};
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000299 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
300 tcp->pid, names[personality]);
301 }
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100302# elif defined(TILE)
303 if (!qflag) {
304 static const char *const names[] = {"64-bit", "32-bit"};
305 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
306 tcp->pid, names[personality]);
307 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100308# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000309}
310#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000311
Roland McGrath9797ceb2002-12-30 10:23:00 +0000312static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000313
Roland McGrathe10e62a2004-09-04 04:20:43 +0000314static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000315 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000316 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000317 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000318 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000319} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000320 { QUAL_TRACE, "trace", qual_syscall, "system call" },
321 { QUAL_TRACE, "t", qual_syscall, "system call" },
322 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
323 { QUAL_ABBREV, "a", qual_syscall, "system call" },
324 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
325 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
326 { QUAL_RAW, "raw", qual_syscall, "system call" },
327 { QUAL_RAW, "x", qual_syscall, "system call" },
328 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
329 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
330 { QUAL_SIGNAL, "s", qual_signal, "signal" },
331 { QUAL_FAULT, "fault", qual_fault, "fault" },
332 { QUAL_FAULT, "faults", qual_fault, "fault" },
333 { QUAL_FAULT, "m", qual_fault, "fault" },
334 { QUAL_READ, "read", qual_desc, "descriptor" },
335 { QUAL_READ, "reads", qual_desc, "descriptor" },
336 { QUAL_READ, "r", qual_desc, "descriptor" },
337 { QUAL_WRITE, "write", qual_desc, "descriptor" },
338 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
339 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000340 { 0, NULL, NULL, NULL },
341};
342
Roland McGrath9797ceb2002-12-30 10:23:00 +0000343static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000344qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000345{
Roland McGrath138c6a32006-01-12 09:50:49 +0000346 if (pers == 0 || pers < 0) {
347 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000348 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000349 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000350 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000351 }
352
353#if SUPPORTED_PERSONALITIES >= 2
354 if (pers == 1 || pers < 0) {
355 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000356 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000357 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000358 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000359 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100360#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000361
362#if SUPPORTED_PERSONALITIES >= 3
363 if (pers == 2 || pers < 0) {
364 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000365 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000366 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000367 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000368 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100369#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000370}
371
372static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000373qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000374{
375 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000376 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000377
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100378 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000379 int i = string_to_uint(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000380 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000381 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000382 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000383 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000384 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000385 for (i = 0; i < nsyscalls0; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000386 if (sysent0[i].sys_name &&
387 strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000388 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000389 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000390 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000391
392#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000393 for (i = 0; i < nsyscalls1; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000394 if (sysent1[i].sys_name &&
395 strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000396 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000397 rc = 0;
398 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100399#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000400
401#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000402 for (i = 0; i < nsyscalls2; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000403 if (sysent2[i].sys_name &&
404 strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000405 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000406 rc = 0;
407 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100408#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000409
Roland McGrathfe6b3522005-02-02 04:40:11 +0000410 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000411}
412
413static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000414qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000415{
416 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000417
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100418 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000419 int signo = string_to_uint(s);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000420 if (signo < 0 || signo >= MAX_QUALS)
421 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000422 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000423 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000424 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000425 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000426 s += 3;
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100427 for (i = 0; i <= NSIG; i++) {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000428 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000429 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000430 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000431 }
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100432 }
Roland McGrath76421df2005-02-02 03:51:18 +0000433 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000434}
435
436static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000437qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000438{
439 return -1;
440}
441
442static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000443qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000444{
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100445 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000446 int desc = string_to_uint(s);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000447 if (desc < 0 || desc >= MAX_QUALS)
448 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000449 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000450 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000451 }
452 return -1;
453}
454
455static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000456lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000457{
458 if (strcmp(s, "file") == 0)
459 return TRACE_FILE;
460 if (strcmp(s, "ipc") == 0)
461 return TRACE_IPC;
462 if (strcmp(s, "network") == 0)
463 return TRACE_NETWORK;
464 if (strcmp(s, "process") == 0)
465 return TRACE_PROCESS;
466 if (strcmp(s, "signal") == 0)
467 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000468 if (strcmp(s, "desc") == 0)
469 return TRACE_DESC;
Namhyung Kim96792962012-10-24 11:41:57 +0900470 if (strcmp(s, "memory") == 0)
471 return TRACE_MEMORY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000472 return -1;
473}
474
475void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000476qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000477{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000478 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000479 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000480 char *copy;
481 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000482 int i, n;
483
484 opt = &qual_options[0];
485 for (i = 0; (p = qual_options[i].option_name); i++) {
486 n = strlen(p);
487 if (strncmp(s, p, n) == 0 && s[n] == '=') {
488 opt = &qual_options[i];
489 s += n + 1;
490 break;
491 }
492 }
493 not = 0;
494 if (*s == '!') {
495 not = 1;
496 s++;
497 }
498 if (strcmp(s, "none") == 0) {
499 not = 1 - not;
500 s = "all";
501 }
502 if (strcmp(s, "all") == 0) {
503 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000504 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000505 }
506 return;
507 }
508 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000509 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000510 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200511 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200512 if (!copy)
513 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000514 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000515 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000516 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000517 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000518 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000519
520#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000521 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000522 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000523 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100524#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000525
526#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000527 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000528 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000529 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100530#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000531
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000532 continue;
533 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000534 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100535 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000536 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000537 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000538 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000539 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000540 return;
541}
542
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000543#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000544static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000545decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000546{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000547 unsigned long addr;
548 unsigned int i, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000549
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000550 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
551 return;
552
553 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
554 addr = tcp->u_arg[1];
555 tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100556 size = current_wordsize;
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000557 for (i = 0; i < tcp->u_nargs; ++i) {
558 if (size == sizeof(int)) {
559 unsigned int arg;
560 if (umove(tcp, addr, &arg) < 0)
561 arg = 0;
562 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000563 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000564 else {
565 unsigned long arg;
566 if (umove(tcp, addr, &arg) < 0)
567 arg = 0;
568 tcp->u_arg[i] = arg;
569 }
570 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000571 }
572}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000573#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400574
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000575#ifdef SYS_ipc_subcall
576static void
577decode_ipc_subcall(struct tcb *tcp)
578{
579 unsigned int i;
580
581 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
582 return;
583
584 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
585 tcp->u_nargs = sysent[tcp->scno].nargs;
586 for (i = 0; i < tcp->u_nargs; i++)
587 tcp->u_arg[i] = tcp->u_arg[i + 1];
588}
589#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000590
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200591int
592printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000593{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200594 if (entering(tcp)) {
595 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000596
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200597 for (i = 0; i < tcp->u_nargs; i++)
598 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
599 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000600 return 0;
601}
602
Denys Vlasenko72879c62012-02-27 14:18:02 +0100603int
604printargs_lu(struct tcb *tcp)
605{
606 if (entering(tcp)) {
607 int i;
608
609 for (i = 0; i < tcp->u_nargs; i++)
610 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
611 }
612 return 0;
613}
614
615int
616printargs_ld(struct tcb *tcp)
617{
618 if (entering(tcp)) {
619 int i;
620
621 for (i = 0; i < tcp->u_nargs; i++)
622 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
623 }
624 return 0;
625}
626
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100627#if defined(SPARC) || defined(SPARC64) || defined(IA64) || defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200628long
629getrval2(struct tcb *tcp)
630{
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100631 long val;
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200632
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100633# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200634 val = regs.u_regs[U_REG_O1];
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100635# elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200636 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
637 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100638# elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200639 if (upeek(tcp, PT_R9, &val) < 0)
640 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100641# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200642
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200643 return val;
644}
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100645#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200646
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200647int
648is_restart_error(struct tcb *tcp)
649{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200650 switch (tcp->u_error) {
651 case ERESTARTSYS:
652 case ERESTARTNOINTR:
653 case ERESTARTNOHAND:
654 case ERESTART_RESTARTBLOCK:
655 return 1;
656 default:
657 break;
658 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200659 return 0;
660}
661
Denys Vlasenko523635f2012-02-25 02:44:25 +0100662#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100663struct pt_regs i386_regs;
H.J. Lu35be5812012-04-16 13:00:01 +0200664#elif defined(X86_64) || defined(X32)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100665/*
666 * On 32 bits, pt_regs and user_regs_struct are the same,
667 * but on 64 bits, user_regs_struct has six more fields:
668 * fs_base, gs_base, ds, es, fs, gs.
669 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
670 */
671static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100672#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200673long ia32 = 0; /* not static */
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100674static long ia64_r8, ia64_r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100675#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +0100676static long ppc_result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100677#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100678static long m68k_d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100679#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200680static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100681#elif defined(ARM)
Denys Vlasenko401374e2013-02-06 18:24:39 +0100682struct pt_regs arm_regs; /* not static */
Steve McIntyred8d3bd32012-10-24 17:58:16 +0100683#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100684static union {
685 struct user_pt_regs aarch64;
686 struct arm_pt_regs arm;
687} arm_regs_union;
688# define aarch64_regs arm_regs_union.aarch64
689# define arm_regs arm_regs_union.arm
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100690static struct iovec aarch64_io = {
691 .iov_base = &aarch64_regs
692};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100693#elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200694static long r0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100695static long alpha_a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100696#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200697static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100698#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100699struct pt_regs regs; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100700#elif defined(LINUX_MIPSN32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200701static long long a3;
702static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100703#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200704static long a3;
705static long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100706#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200707static long gpr2;
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200708static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100709#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100710static long hppa_r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100711#elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200712static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100713#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100714static long sh64_r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100715#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100716static long cris_r10;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100717#elif defined(TILE)
718struct pt_regs tile_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100719#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100720static long microblaze_r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100721#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000722
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100723void
724printcall(struct tcb *tcp)
725{
726#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
727 sizeof(long) == 8 ? "[????????????????] " : \
728 NULL /* crash */)
729 if (get_regs_error) {
730 PRINTBADPC;
731 return;
732 }
733#if defined(I386)
734 tprintf("[%08lx] ", i386_regs.eip);
735#elif defined(S390) || defined(S390X)
736 long psw;
737 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
738 PRINTBADPC;
739 return;
740 }
741# ifdef S390
742 tprintf("[%08lx] ", psw);
743# elif S390X
Dmitry V. Levinddba73e2013-02-05 19:01:58 +0000744 tprintf("[%016lx] ", psw);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100745# endif
746#elif defined(X86_64) || defined(X32)
Dmitry V. Levinddba73e2013-02-05 19:01:58 +0000747 tprintf("[%016lx] ", (unsigned long) x86_64_regs.rip);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100748#elif defined(IA64)
749 long ip;
750
751 if (upeek(tcp, PT_B0, &ip) < 0) {
752 PRINTBADPC;
753 return;
754 }
755 tprintf("[%08lx] ", ip);
756#elif defined(POWERPC)
757 long pc;
758
759 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
760 PRINTBADPC;
761 return;
762 }
763# ifdef POWERPC64
764 tprintf("[%016lx] ", pc);
765# else
766 tprintf("[%08lx] ", pc);
767# endif
768#elif defined(M68K)
769 long pc;
770
771 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
772 tprints("[????????] ");
773 return;
774 }
775 tprintf("[%08lx] ", pc);
776#elif defined(ALPHA)
777 long pc;
778
779 if (upeek(tcp, REG_PC, &pc) < 0) {
780 tprints("[????????????????] ");
781 return;
782 }
783 tprintf("[%08lx] ", pc);
784#elif defined(SPARC)
785 tprintf("[%08lx] ", regs.pc);
786#elif defined(SPARC64)
787 tprintf("[%08lx] ", regs.tpc);
788#elif defined(HPPA)
789 long pc;
790
791 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
792 tprints("[????????] ");
793 return;
794 }
795 tprintf("[%08lx] ", pc);
796#elif defined(MIPS)
797 long pc;
798
799 if (upeek(tcp, REG_EPC, &pc) < 0) {
800 tprints("[????????] ");
801 return;
802 }
803 tprintf("[%08lx] ", pc);
804#elif defined(SH)
805 long pc;
806
807 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
808 tprints("[????????] ");
809 return;
810 }
811 tprintf("[%08lx] ", pc);
812#elif defined(SH64)
813 long pc;
814
815 if (upeek(tcp, REG_PC, &pc) < 0) {
816 tprints("[????????????????] ");
817 return;
818 }
819 tprintf("[%08lx] ", pc);
820#elif defined(ARM)
Denys Vlasenko401374e2013-02-06 18:24:39 +0100821 tprintf("[%08lx] ", arm_regs.ARM_pc);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100822#elif defined(AARCH64)
823 /* tprintf("[%016lx] ", aarch64_regs.regs[???]); */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100824#elif defined(AVR32)
825 tprintf("[%08lx] ", regs.pc);
826#elif defined(BFIN)
827 long pc;
828
829 if (upeek(tcp, PT_PC, &pc) < 0) {
830 PRINTBADPC;
831 return;
832 }
833 tprintf("[%08lx] ", pc);
834#elif defined(CRISV10)
835 long pc;
836
837 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
838 PRINTBADPC;
839 return;
840 }
841 tprintf("[%08lx] ", pc);
842#elif defined(CRISV32)
843 long pc;
844
845 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
846 PRINTBADPC;
847 return;
848 }
849 tprintf("[%08lx] ", pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100850#elif defined(TILE)
851# ifdef _LP64
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500852 tprintf("[%016lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100853# else
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500854 tprintf("[%08lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100855# endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100856#endif /* architecture */
857}
858
859#ifndef get_regs
860long get_regs_error;
861void get_regs(pid_t pid)
862{
863# if defined(AVR32)
864 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
865# elif defined(I386)
866 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &i386_regs);
867# elif defined(X86_64) || defined(X32)
868 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &x86_64_regs);
Denys Vlasenko401374e2013-02-06 18:24:39 +0100869# elif defined(ARM)
870 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (void *)&arm_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100871# elif defined(AARCH64)
872 /*aarch64_io.iov_base = &aarch64_regs; - already is */
873 aarch64_io.iov_len = sizeof(aarch64_regs);
874 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void *)&aarch64_io);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100875# if 0
876 /* Paranoia checks */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100877 if (get_regs_error)
878 return;
879 switch (aarch64_io.iov_len) {
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100880 case sizeof(aarch64_regs):
881 /* We are in 64-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100882 break;
883 case sizeof(arm_regs):
884 /* We are in 32-bit mode */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100885 break;
886 default:
887 get_regs_error = -1;
888 break;
889 }
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100890# endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100891# elif defined(SPARC) || defined(SPARC64)
892 get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&regs, 0);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100893# elif defined(TILE)
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500894 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &tile_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100895# endif
896}
897#endif
898
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200899/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100900 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
901 * 1: ok, continue in trace_syscall_entering().
902 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200903 * ("????" etc) and bail out.
904 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100905static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200906get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000907{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000908 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000909
Denys Vlasenko523635f2012-02-25 02:44:25 +0100910#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000911 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200912 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000913
914 if (syscall_mode != -ENOSYS) {
915 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000916 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000917 */
918 scno = syscall_mode;
919 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000920 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000921 * Old style of "passing" the scno via the SVC instruction.
922 */
Denys Vlasenko7ba8e722013-02-08 15:50:05 +0100923 long psw;
Michal Ludvig882eda82002-11-11 12:50:47 +0000924 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200925 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200926 static const int gpr_offset[16] = {
927 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
928 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
929 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
930 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
931 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000932
Denys Vlasenko7ba8e722013-02-08 15:50:05 +0100933 if (upeek(tcp, PT_PSWADDR, &psw) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000934 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000935 errno = 0;
Denys Vlasenko7ba8e722013-02-08 15:50:05 +0100936 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(psw - sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000937 if (errno) {
Denys Vlasenko7ba8e722013-02-08 15:50:05 +0100938 perror_msg("%s", "peektext(psw-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000939 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000940 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000941
942 /*
943 * We have to check if the SVC got executed directly or via an
944 * EXECUTE instruction. In case of EXECUTE it is necessary to do
945 * instruction decoding to derive the system call number.
946 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
947 * so that this doesn't work if a SVC opcode is part of an EXECUTE
948 * opcode. Since there is no way to find out the opcode size this
949 * is the best we can do...
950 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000951 if ((opcode & 0xff00) == 0x0a00) {
952 /* SVC opcode */
953 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000954 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000955 else {
956 /* SVC got executed by EXECUTE instruction */
957
958 /*
959 * Do instruction decoding of EXECUTE. If you really want to
960 * understand this, read the Principles of Operations.
961 */
962 svc_addr = (void *) (opcode & 0xfff);
963
964 tmp = 0;
965 offset_reg = (opcode & 0x000f0000) >> 16;
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
970 tmp = 0;
971 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000972 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000973 return -1;
974 svc_addr += tmp;
975
Denys Vlasenkofb036672009-01-23 16:30:26 +0000976 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000977 if (errno)
978 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100979# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000980 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100981# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000982 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100983# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000984 tmp = 0;
985 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000986 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000987 return -1;
988
989 scno = (scno | tmp) & 0xff;
990 }
991 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100992#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000993 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000994 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100995# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200996 /* TODO: speed up strace by not doing this at every syscall.
997 * We only need to do it after execve.
998 */
999 int currpers;
1000 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +02001001
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001002 /* Check for 64/32 bit mode. */
1003 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
1004 return -1;
1005 /* SF is bit 0 of MSR */
1006 if (val < 0)
1007 currpers = 0;
1008 else
1009 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001010 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001011# endif
1012#elif defined(AVR32)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001013 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001014#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001015 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001016 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001017#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001018 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +02001019#elif defined(X86_64) || defined(X32)
1020# ifndef __X32_SYSCALL_BIT
1021# define __X32_SYSCALL_BIT 0x40000000
1022# endif
1023# ifndef __X32_SYSCALL_MASK
1024# define __X32_SYSCALL_MASK __X32_SYSCALL_BIT
1025# endif
1026
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001027 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001028 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +00001029
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001030 /* Check CS register value. On x86-64 linux it is:
1031 * 0x33 for long mode (64 bit)
1032 * 0x23 for compatibility mode (32 bit)
H.J. Lu35be5812012-04-16 13:00:01 +02001033 * Check DS register value. On x86-64 linux it is:
1034 * 0x2b for x32 mode (x86-64 in 32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001035 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001036 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001037 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +02001038 case 0x33:
1039 if (x86_64_regs.ds == 0x2b) {
1040 currpers = 2;
1041 scno &= ~__X32_SYSCALL_MASK;
1042 } else
1043 currpers = 0;
1044 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001045 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001046 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001047 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001048 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001049 currpers = current_personality;
1050 break;
1051 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001052# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001053 /* This version analyzes the opcode of a syscall instruction.
1054 * (int 0x80 on i386 vs. syscall on x86-64)
1055 * It works, but is too complicated.
1056 */
1057 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +00001058
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001059 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +00001060
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001061 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
1062 rip -= 2;
1063 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +00001064
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001065 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001066 if (errno)
1067 fprintf(stderr, "ptrace_peektext failed: %s\n",
1068 strerror(errno));
1069 switch (call & 0xffff) {
1070 /* x86-64: syscall = 0x0f 0x05 */
1071 case 0x050f: currpers = 0; break;
1072 /* i386: int 0x80 = 0xcd 0x80 */
1073 case 0x80cd: currpers = 1; break;
1074 default:
1075 currpers = current_personality;
1076 fprintf(stderr,
1077 "Unknown syscall opcode (0x%04X) while "
1078 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001079 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001080 break;
1081 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001082# endif
H.J. Lu35be5812012-04-16 13:00:01 +02001083# ifdef X32
H.J. Lu085e4282012-04-17 11:05:04 -07001084 /* Value of currpers:
1085 * 0: 64 bit
1086 * 1: 32 bit
1087 * 2: X32
1088 * Value of current_personality:
1089 * 0: X32
1090 * 1: 32 bit
1091 */
1092 switch (currpers) {
1093 case 0:
1094 fprintf(stderr, "syscall_%lu (...) in unsupported "
1095 "64-bit mode of process PID=%d\n",
1096 scno, tcp->pid);
1097 return 0;
1098 case 2:
1099 currpers = 0;
H.J. Lu35be5812012-04-16 13:00:01 +02001100 }
H.J. Lu35be5812012-04-16 13:00:01 +02001101# endif
H.J. Lu085e4282012-04-17 11:05:04 -07001102 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001103#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001104# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001105 long psr;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001106 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001107 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001108 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001109 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001110 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001111 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001112 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001113 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001114 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001115#elif defined(AARCH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001116 switch (aarch64_io.iov_len) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001117 case sizeof(aarch64_regs):
1118 /* We are in 64-bit mode */
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001119 scno = aarch64_regs.regs[8];
1120 update_personality(tcp, 1);
1121 break;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001122 case sizeof(arm_regs):
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001123 /* We are in 32-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001124 scno = arm_regs.ARM_r7;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001125 update_personality(tcp, 0);
1126 break;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001127 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001128#elif defined(ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001129 /*
1130 * We only need to grab the syscall number on syscall entry.
1131 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001132 if (arm_regs.ARM_ip == 0) {
Roland McGrath0f87c492003-06-03 23:29:04 +00001133 /*
Denys Vlasenko401374e2013-02-06 18:24:39 +01001134 * Note: we only deal with 32-bit CPUs here
Roland McGrath0f87c492003-06-03 23:29:04 +00001135 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001136 if (arm_regs.ARM_cpsr & 0x20) {
Roland McGrath0f87c492003-06-03 23:29:04 +00001137 /*
1138 * Get the Thumb-mode system call number
1139 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001140 scno = arm_regs.ARM_r7;
Roland McGrath0f87c492003-06-03 23:29:04 +00001141 } else {
1142 /*
1143 * Get the ARM-mode system call number
1144 */
1145 errno = 0;
Denys Vlasenko401374e2013-02-06 18:24:39 +01001146 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(arm_regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +00001147 if (errno)
1148 return -1;
1149
Roland McGrathf691bd22006-04-25 07:34:41 +00001150 /* Handle the EABI syscall convention. We do not
1151 bother converting structures between the two
1152 ABIs, but basic functionality should work even
1153 if strace and the traced program have different
1154 ABIs. */
1155 if (scno == 0xef000000) {
Denys Vlasenko401374e2013-02-06 18:24:39 +01001156 scno = arm_regs.ARM_r7;
Roland McGrathf691bd22006-04-25 07:34:41 +00001157 } else {
1158 if ((scno & 0x0ff00000) != 0x0f900000) {
1159 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1160 scno);
1161 return -1;
1162 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001163
Roland McGrathf691bd22006-04-25 07:34:41 +00001164 /*
1165 * Fixup the syscall number
1166 */
1167 scno &= 0x000fffff;
1168 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001169 }
Roland McGrath56703312008-05-20 01:35:55 +00001170 if (scno & 0x0f0000) {
1171 /*
1172 * Handle ARM specific syscall
1173 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001174 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +00001175 scno &= 0x0000ffff;
1176 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001177 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001178
Roland McGrath0f87c492003-06-03 23:29:04 +00001179 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001180 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1181 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001182 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001183#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001184 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001185 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001186#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001187 unsigned long long regs[38];
1188
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001189 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001190 return -1;
1191 a3 = regs[REG_A3];
1192 r2 = regs[REG_V0];
1193
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001194 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001195 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001196 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001197 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001198 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001199 return 0;
1200 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001201 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001202#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001203 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001204 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001205 if (upeek(tcp, REG_V0, &scno) < 0)
1206 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001207
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001208 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001209 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001210 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001211 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001212 return 0;
1213 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001214 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001215#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001216 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001217 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001218 if (upeek(tcp, REG_R0, &scno) < 0)
1219 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001220
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001221 /*
1222 * Do some sanity checks to figure out if it's
1223 * really a syscall entry
1224 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001225 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001226 if (alpha_a3 == 0 || alpha_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001227 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001228 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001229 return 0;
1230 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001231 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001232#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001233 /* Disassemble the syscall trap. */
1234 /* Retrieve the syscall trap instruction. */
Denys Vlasenko46455822013-02-05 17:02:59 +01001235 unsigned long trap;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001236 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001237# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001238 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1239 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001240# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001241 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001242# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001243 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001244 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001245
1246 /* Disassemble the trap to see what personality to use. */
1247 switch (trap) {
1248 case 0x91d02010:
1249 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001250 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001251 break;
1252 case 0x91d0206d:
1253 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001254 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001255 break;
1256 case 0x91d02000:
1257 /* SunOS syscall trap. (pers 1) */
1258 fprintf(stderr, "syscall: SunOS no support\n");
1259 return -1;
1260 case 0x91d02008:
1261 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001262 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001263 break;
1264 case 0x91d02009:
1265 /* NetBSD/FreeBSD syscall trap. */
1266 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1267 return -1;
1268 case 0x91d02027:
1269 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001270 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001271 break;
1272 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001273# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001274 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001275# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001276 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001277# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001278 return -1;
1279 }
1280
1281 /* Extract the system call number from the registers. */
1282 if (trap == 0x91d02027)
1283 scno = 156;
1284 else
1285 scno = regs.u_regs[U_REG_G1];
1286 if (scno == 0) {
1287 scno = regs.u_regs[U_REG_O0];
1288 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1289 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001290#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001291 if (upeek(tcp, PT_GR20, &scno) < 0)
1292 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001293#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001294 /*
1295 * In the new syscall ABI, the system call number is in R3.
1296 */
1297 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1298 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001299
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001300 if (scno < 0) {
1301 /* Odd as it may seem, a glibc bug has been known to cause
1302 glibc to issue bogus negative syscall numbers. So for
1303 our purposes, make strace print what it *should* have been */
1304 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001305 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001306 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001307 "Detected glibc bug: bogus system call"
1308 " number = %ld, correcting to %ld\n",
1309 scno,
1310 correct_scno);
1311 scno = correct_scno;
1312 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001313#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001314 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001315 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001316 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001317#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001318 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1319 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001320#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001321 int currpers;
1322 scno = tile_regs.regs[10];
1323# ifdef __tilepro__
1324 currpers = 1;
1325# else
1326 if (tile_regs.flags & PT_FLAGS_COMPAT)
1327 currpers = 1;
1328 else
1329 currpers = 0;
1330# endif
1331 update_personality(tcp, currpers);
1332
1333 if (!(tcp->flags & TCB_INSYSCALL)) {
1334 /* Check if we return from execve. */
1335 if (tcp->flags & TCB_WAITEXECVE) {
1336 tcp->flags &= ~TCB_WAITEXECVE;
1337 return 0;
1338 }
1339 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001340#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001341 if (upeek(tcp, 0, &scno) < 0)
1342 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001343#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001344
Denys Vlasenko523635f2012-02-25 02:44:25 +01001345#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001346 /* new syscall ABI returns result in R0 */
1347 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1348 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001349#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001350 /* ABI defines result returned in r9 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001351 if (upeek(tcp, REG_GENERAL(9), (long *)&sh64_r9) < 0)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001352 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001353#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001354
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001355 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001356 return 1;
1357}
1358
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001359/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001360 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001361 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1362 * 1: ok, continue in trace_syscall_entering().
1363 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001364 * ("????" etc) and bail out.
1365 */
Roland McGratha4d48532005-06-08 20:45:28 +00001366static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001367syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001368{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001369 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001370#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001371 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001372 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001373 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1374 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001375 }
H.J. Lu35be5812012-04-16 13:00:01 +02001376#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001377 {
1378 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001379 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001380 rax = (int)rax; /* sign extend from 32 bits */
1381 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001382 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001383 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1384 return 0;
1385 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001386 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001387#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001388 /* TODO: we already fetched PT_GPR2 in get_scno
1389 * and stored it in syscall_mode, reuse it here
1390 * instead of re-fetching?
1391 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001392 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001393 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001394 if (syscall_mode != -ENOSYS)
1395 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001396 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001397 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001398 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001399 return 0;
1400 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001401#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001402 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001403 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001404 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001405 if (m68k_d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001406 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001407 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", m68k_d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001408 return 0;
1409 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001410#elif defined(IA64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001411 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001412 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001413 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001414 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001415 if (ia32 && ia64_r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001416 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001417 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", ia64_r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001418 return 0;
1419 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001420#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001421 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001422 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001423 if (cris_r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001424 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001425 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", cris_r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001426 return 0;
1427 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001428#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001429 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001430 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001431 if (microblaze_r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001432 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001433 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", microblaze_r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001434 return 0;
1435 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001436#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001437 return 1;
1438}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001439
Denys Vlasenko146b9442012-03-18 22:10:48 +01001440static void
1441internal_fork(struct tcb *tcp)
1442{
1443#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1444# define ARG_FLAGS 1
1445#else
1446# define ARG_FLAGS 0
1447#endif
1448#ifndef CLONE_UNTRACED
1449# define CLONE_UNTRACED 0x00800000
1450#endif
1451 if ((ptrace_setoptions
1452 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1453 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1454 return;
1455
1456 if (!followfork)
1457 return;
1458
1459 if (entering(tcp)) {
1460 /*
1461 * We won't see the new child if clone is called with
1462 * CLONE_UNTRACED, so we keep the same logic with that option
1463 * and don't trace it.
1464 */
1465 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1466 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1467 return;
1468 setbpt(tcp);
1469 } else {
1470 if (tcp->flags & TCB_BPTSET)
1471 clearbpt(tcp);
1472 }
1473}
1474
1475#if defined(TCB_WAITEXECVE)
1476static void
1477internal_exec(struct tcb *tcp)
1478{
1479 /* Maybe we have post-execve SIGTRAP suppressed? */
1480 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1481 return; /* yes, no need to do anything */
1482
1483 if (exiting(tcp) && syserror(tcp))
1484 /* Error in execve, no post-execve SIGTRAP expected */
1485 tcp->flags &= ~TCB_WAITEXECVE;
1486 else
1487 tcp->flags |= TCB_WAITEXECVE;
1488}
1489#endif
1490
1491static void
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001492syscall_fixup_for_fork_exec(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001493{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001494 /*
1495 * We must always trace a few critical system calls in order to
1496 * correctly support following forks in the presence of tracing
1497 * qualifiers.
1498 */
1499 int (*func)();
1500
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001501 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001502 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001503
1504 func = sysent[tcp->scno].sys_func;
1505
1506 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001507 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001508 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001509 ) {
1510 internal_fork(tcp);
1511 return;
1512 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001513
Denys Vlasenko84703742012-02-25 02:38:52 +01001514#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001515 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001516# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001517 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001518# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001519 ) {
1520 internal_exec(tcp);
1521 return;
1522 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001523#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001524}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001525
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001526/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001527static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001528get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001529{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001530 int i, nargs;
1531
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001532 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001533 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001534 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001535 nargs = tcp->u_nargs = MAX_ARGS;
1536
Denys Vlasenko523635f2012-02-25 02:44:25 +01001537#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001538 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001539 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1540 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001541#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001542 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001543 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1544 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001545#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001546 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001547 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001548 long rbs_end;
1549 /* be backwards compatible with kernel < 2.4.4... */
1550# ifndef PT_RBS_END
1551# define PT_RBS_END PT_AR_BSP
1552# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001553
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001554 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1555 return -1;
1556 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001557 return -1;
1558
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001559 sof = (cfm >> 0) & 0x7f;
1560 sol = (cfm >> 7) & 0x7f;
1561 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1562
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001563 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001564 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1565 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1566 return -1;
1567 }
1568 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001569 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1570 PT_R9 /* ECX = out1 */,
1571 PT_R10 /* EDX = out2 */,
1572 PT_R14 /* ESI = out3 */,
1573 PT_R15 /* EDI = out4 */,
1574 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001575
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001576 for (i = 0; i < nargs; ++i) {
1577 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1578 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001579 /* truncate away IVE sign-extension */
1580 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001581 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001582 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001583#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001584 /* N32 and N64 both use up to six registers. */
1585 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001586
1587 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1588 return -1;
1589
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001590 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001591 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001592# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001593 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001594# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001595 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001596#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001597 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001598 long sp;
1599
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001600 if (upeek(tcp, REG_SP, &sp) < 0)
1601 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001602 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001603 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1604 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001605 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001606 (char *)(tcp->u_arg + 4));
1607 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001608 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001609 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001610 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001611 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001612#elif defined(POWERPC)
1613# ifndef PT_ORIG_R3
1614# define PT_ORIG_R3 34
1615# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001616 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001617 if (upeek(tcp, (i==0) ?
1618 (sizeof(unsigned long) * PT_ORIG_R3) :
1619 ((i+PT_R3) * sizeof(unsigned long)),
1620 &tcp->u_arg[i]) < 0)
1621 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001622 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001623#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001624 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001625 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001626#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001627 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001628 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1629 return -1;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001630#elif defined(ARM) || defined(AARCH64)
1631# if defined(AARCH64)
1632 if (tcp->currpers == 1)
1633 for (i = 0; i < nargs; ++i)
1634 tcp->u_arg[i] = aarch64_regs.regs[i];
1635 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001636# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001637 for (i = 0; i < nargs; ++i)
Denys Vlasenko401374e2013-02-06 18:24:39 +01001638 tcp->u_arg[i] = arm_regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001639#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001640 (void)i;
1641 (void)nargs;
1642 tcp->u_arg[0] = regs.r12;
1643 tcp->u_arg[1] = regs.r11;
1644 tcp->u_arg[2] = regs.r10;
1645 tcp->u_arg[3] = regs.r9;
1646 tcp->u_arg[4] = regs.r5;
1647 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001648#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001649 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 +02001650
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001651 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001652 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1653 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001654#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001655 static const int syscall_regs[MAX_ARGS] = {
1656 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1657 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001658 };
1659
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001660 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001661 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001662 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001663#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001664 int i;
1665 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001666 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001667
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001668 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001669 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1670 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001671#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001672 (void)i;
1673 (void)nargs;
H.J. Lu35be5812012-04-16 13:00:01 +02001674 if (current_personality != 1) { /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001675 tcp->u_arg[0] = x86_64_regs.rdi;
1676 tcp->u_arg[1] = x86_64_regs.rsi;
1677 tcp->u_arg[2] = x86_64_regs.rdx;
1678 tcp->u_arg[3] = x86_64_regs.r10;
1679 tcp->u_arg[4] = x86_64_regs.r8;
1680 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001681# ifdef X32
1682 tcp->ext_arg[0] = x86_64_regs.rdi;
1683 tcp->ext_arg[1] = x86_64_regs.rsi;
1684 tcp->ext_arg[2] = x86_64_regs.rdx;
1685 tcp->ext_arg[3] = x86_64_regs.r10;
1686 tcp->ext_arg[4] = x86_64_regs.r8;
1687 tcp->ext_arg[5] = x86_64_regs.r9;
1688# endif
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001689 } else { /* i386 ABI */
1690 /* Sign-extend lower 32 bits */
1691 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1692 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1693 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1694 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1695 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1696 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1697 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001698#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001699 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001700 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1701 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001702#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001703 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001704 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001705 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001706 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001707
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001708 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001709 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1710 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001711#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001712 for (i = 0; i < nargs; ++i)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001713 tcp->u_arg[i] = tile_regs.regs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001714#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001715 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001716 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1717 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001718#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001719 (void)i;
1720 (void)nargs;
1721 tcp->u_arg[0] = i386_regs.ebx;
1722 tcp->u_arg[1] = i386_regs.ecx;
1723 tcp->u_arg[2] = i386_regs.edx;
1724 tcp->u_arg[3] = i386_regs.esi;
1725 tcp->u_arg[4] = i386_regs.edi;
1726 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001727#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001728 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001729 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1730 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001731#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001732 return 1;
1733}
1734
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001735static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001736trace_syscall_entering(struct tcb *tcp)
1737{
1738 int res, scno_good;
1739
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001740#if defined TCB_WAITEXECVE
1741 if (tcp->flags & TCB_WAITEXECVE) {
1742 /* This is the post-execve SIGTRAP. */
1743 tcp->flags &= ~TCB_WAITEXECVE;
1744 return 0;
1745 }
1746#endif
1747
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001748 scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001749 if (res == 0)
1750 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001751 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001752 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001753 if (res == 0)
1754 return res;
1755 if (res == 1)
1756 res = get_syscall_args(tcp);
1757 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001758
1759 if (res != 1) {
1760 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001761 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001762 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001763 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001764 tprintf("syscall_%lu(", tcp->scno);
1765 else
1766 tprintf("%s(", sysent[tcp->scno].sys_name);
1767 /*
1768 * " <unavailable>" will be added later by the code which
1769 * detects ptrace errors.
1770 */
1771 goto ret;
1772 }
1773
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001774#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1775 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001776# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001777 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001778 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001779 break;
1780 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001781# endif
1782# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001783 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001784 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001785 break;
1786 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001787# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001788 break;
1789 }
1790#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1791
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001792 if (need_fork_exec_workarounds)
1793 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001794
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001795 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001796 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1797 (tracing_paths && !pathtrace_match(tcp))) {
1798 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1799 return 0;
1800 }
1801
1802 tcp->flags &= ~TCB_FILTERED;
1803
1804 if (cflag == CFLAG_ONLY_STATS) {
1805 res = 0;
1806 goto ret;
1807 }
1808
1809 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001810 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001811 tprintf("syscall_%lu(", tcp->scno);
1812 else
1813 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001814 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001815 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1816 sysent[tcp->scno].sys_func != sys_exit))
1817 res = printargs(tcp);
1818 else
1819 res = (*sysent[tcp->scno].sys_func)(tcp);
1820
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001821 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001822 ret:
1823 tcp->flags |= TCB_INSYSCALL;
1824 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001825 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001826 gettimeofday(&tcp->etime, NULL);
1827 return res;
1828}
1829
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001830/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001831 * 1: ok, continue in trace_syscall_exiting().
1832 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001833 * ("????" etc) and bail out.
1834 */
1835static int
1836get_syscall_result(struct tcb *tcp)
1837{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001838#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001839 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1840 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001841#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001842# define SO_MASK 0x10000000
1843 {
1844 long flags;
1845 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1846 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001847 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001848 return -1;
1849 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001850 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001851 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001852#elif defined(AVR32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001853 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001854#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001855 if (upeek(tcp, PT_R0, &r0) < 0)
1856 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001857#elif defined(I386)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001858 /* already done by get_regs */
H.J. Lu35be5812012-04-16 13:00:01 +02001859#elif defined(X86_64) || defined(X32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001860 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001861#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001862# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001863 long psr;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001864 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1865 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001866 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001867 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001868 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001869 return -1;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001870#elif defined(ARM)
1871 /* already done by get_regs */
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001872#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001873 /* register reading already done by get_regs */
1874
1875 /* Used to do this, but we did it on syscall entry already: */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001876 /* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
1877 * else it's personality 0.
1878 */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001879 /*update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));*/
Denys Vlasenko523635f2012-02-25 02:44:25 +01001880#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001881 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001882 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001883#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001884 unsigned long long regs[38];
1885
1886 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1887 return -1;
1888 a3 = regs[REG_A3];
1889 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001890#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001891 if (upeek(tcp, REG_A3, &a3) < 0)
1892 return -1;
1893 if (upeek(tcp, REG_V0, &r2) < 0)
1894 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001895#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001896 if (upeek(tcp, REG_A3, &a3) < 0)
1897 return -1;
1898 if (upeek(tcp, REG_R0, &r0) < 0)
1899 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001900#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001901 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001902#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001903 if (upeek(tcp, PT_GR28, &hppa_r28) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001904 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001905#elif defined(SH)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001906 /* new syscall ABI returns result in R0 */
1907 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1908 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001909#elif defined(SH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001910 /* ABI defines result returned in r9 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001911 if (upeek(tcp, REG_GENERAL(9), (long *)&sh64_r9) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001912 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001913#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001914 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001915 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001916#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001917 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001918#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001919 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001920 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001921#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001922 return 1;
1923}
1924
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001925/* Called at each syscall exit */
1926static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001927syscall_fixup_on_sysexit(struct tcb *tcp)
1928{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001929#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001930 if (syscall_mode != -ENOSYS)
1931 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001932 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001933 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1934 /*
1935 * Return from execve.
1936 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1937 * flag set for the post-execve SIGTRAP to see and reset.
1938 */
1939 gpr2 = 0;
1940 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001941#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001942}
1943
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001944/*
1945 * Check the syscall return value register value for whether it is
1946 * a negated errno code indicating an error, or a success return value.
1947 */
1948static inline int
1949is_negated_errno(unsigned long int val)
1950{
1951 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001952#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001953 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001954 val = (unsigned int) val;
1955 max = (unsigned int) max;
1956 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001957#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001958 return val > max;
1959}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001960
Denys Vlasenko907735a2012-03-21 00:23:16 +01001961/* Returns:
1962 * 1: ok, continue in trace_syscall_exiting().
1963 * -1: error, trace_syscall_exiting() should print error indicator
1964 * ("????" etc) and bail out.
1965 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001966static int
1967get_error(struct tcb *tcp)
1968{
1969 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001970 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001971 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001972 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1973 check_errno = 0;
1974 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001975#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001976 if (check_errno && is_negated_errno(gpr2)) {
1977 tcp->u_rval = -1;
1978 u_error = -gpr2;
1979 }
1980 else {
1981 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001982 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001983#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001984 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001985 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001986 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001987 }
1988 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001989 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001990 }
H.J. Lu35be5812012-04-16 13:00:01 +02001991#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001992 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001993 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001994 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001995 }
1996 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001997 tcp->u_rval = x86_64_regs.rax;
H.J. Lu35be5812012-04-16 13:00:01 +02001998# if defined(X32)
1999 tcp->u_lrval = x86_64_regs.rax;
2000# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002001 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002002#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002003 if (ia32) {
2004 int err;
2005
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002006 err = (int)ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002007 if (check_errno && is_negated_errno(err)) {
2008 tcp->u_rval = -1;
2009 u_error = -err;
2010 }
2011 else {
2012 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002013 }
2014 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002015 if (check_errno && ia64_r10) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002016 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002017 u_error = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002018 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002019 tcp->u_rval = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002020 }
2021 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002022#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002023 if (check_errno && a3) {
2024 tcp->u_rval = -1;
2025 u_error = r2;
2026 } else {
2027 tcp->u_rval = r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002028# if defined(LINUX_MIPSN32)
2029 tcp->u_lrval = r2;
2030# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002031 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002032#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002033 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002034 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002035 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002036 }
2037 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002038 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002039 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002040#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002041 if (check_errno && is_negated_errno(m68k_d0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002042 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002043 u_error = -m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002044 }
2045 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002046 tcp->u_rval = m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002047 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002048#elif defined(ARM) || defined(AARCH64)
2049# if defined(AARCH64)
2050 if (tcp->currpers == 1) {
2051 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2052 tcp->u_rval = -1;
2053 u_error = -aarch64_regs.regs[0];
2054 }
2055 else {
2056 tcp->u_rval = aarch64_regs.regs[0];
2057 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002058 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002059 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01002060# endif
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002061 {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002062 if (check_errno && is_negated_errno(arm_regs.ARM_r0)) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002063 tcp->u_rval = -1;
Denys Vlasenko401374e2013-02-06 18:24:39 +01002064 u_error = -arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002065 }
2066 else {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002067 tcp->u_rval = arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002068 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002069 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002070#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002071 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
2072 tcp->u_rval = -1;
2073 u_error = -regs.r12;
2074 }
2075 else {
2076 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002077 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002078#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002079 if (check_errno && is_negated_errno(r0)) {
2080 tcp->u_rval = -1;
2081 u_error = -r0;
2082 } else {
2083 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002084 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002085#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002086 if (check_errno && alpha_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002087 tcp->u_rval = -1;
2088 u_error = r0;
2089 }
2090 else {
2091 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002092 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002093#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002094 if (check_errno && regs.psr & PSR_C) {
2095 tcp->u_rval = -1;
2096 u_error = regs.u_regs[U_REG_O0];
2097 }
2098 else {
2099 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002100 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002101#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002102 if (check_errno && regs.tstate & 0x1100000000UL) {
2103 tcp->u_rval = -1;
2104 u_error = regs.u_regs[U_REG_O0];
2105 }
2106 else {
2107 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002108 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002109#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002110 if (check_errno && is_negated_errno(hppa_r28)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002111 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002112 u_error = -hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002113 }
2114 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002115 tcp->u_rval = hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002116 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002117#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002118 if (check_errno && is_negated_errno(r0)) {
2119 tcp->u_rval = -1;
2120 u_error = -r0;
2121 }
2122 else {
2123 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002124 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002125#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002126 if (check_errno && is_negated_errno(sh64_r9)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002127 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002128 u_error = -sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002129 }
2130 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002131 tcp->u_rval = sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002132 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002133#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002134 if (check_errno && cris_r10 && (unsigned) -cris_r10 < nerrnos) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002135 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002136 u_error = -cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002137 }
2138 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002139 tcp->u_rval = cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002140 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002141#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002142 /*
2143 * The standard tile calling convention returns the value (or negative
2144 * errno) in r0, and zero (or positive errno) in r1.
2145 * Until at least kernel 3.8, however, the r1 value is not reflected
2146 * in ptregs at this point, so we use r0 here.
2147 */
2148 if (check_errno && is_negated_errno(tile_regs.regs[0])) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002149 tcp->u_rval = -1;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002150 u_error = -tile_regs.regs[0];
2151 } else {
2152 tcp->u_rval = tile_regs.regs[0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002153 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002154#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002155 if (check_errno && is_negated_errno(microblaze_r3)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002156 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002157 u_error = -microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002158 }
2159 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002160 tcp->u_rval = microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002161 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002162#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002163 tcp->u_error = u_error;
2164 return 1;
2165}
2166
2167static void
2168dumpio(struct tcb *tcp)
2169{
2170 if (syserror(tcp))
2171 return;
2172 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
2173 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002174 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002175 return;
2176 if (sysent[tcp->scno].sys_func == printargs)
2177 return;
2178 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
2179 if (sysent[tcp->scno].sys_func == sys_read ||
2180 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002181 sysent[tcp->scno].sys_func == sys_recv ||
2182 sysent[tcp->scno].sys_func == sys_recvfrom)
2183 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
2184 else if (sysent[tcp->scno].sys_func == sys_readv)
2185 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2186 return;
2187 }
2188 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
2189 if (sysent[tcp->scno].sys_func == sys_write ||
2190 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002191 sysent[tcp->scno].sys_func == sys_send ||
2192 sysent[tcp->scno].sys_func == sys_sendto)
2193 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
2194 else if (sysent[tcp->scno].sys_func == sys_writev)
2195 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2196 return;
2197 }
2198}
2199
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002200static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002201trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002202{
2203 int sys_res;
2204 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002205 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002206 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002207
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002208 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002209 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002210 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002211
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002212#if SUPPORTED_PERSONALITIES > 1
2213 update_personality(tcp, tcp->currpers);
2214#endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002215 res = (get_regs_error ? -1 : get_syscall_result(tcp));
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002216 if (res == 1) {
2217 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01002218 res = get_error(tcp); /* returns 1 or -1 */
2219 if (res == 1) {
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01002220 if (need_fork_exec_workarounds)
2221 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01002222 if (filtered(tcp)) {
2223 goto ret;
2224 }
2225 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002226 }
2227
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002228 if (cflag) {
2229 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002230 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002231 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002232 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002233 }
2234 }
2235
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002236 /* If not in -ff mode, and printing_tcp != tcp,
2237 * then the log currently does not end with output
2238 * of _our syscall entry_, but with something else.
2239 * We need to say which syscall's return is this.
2240 *
2241 * Forced reprinting via TCB_REPRINT is used only by
2242 * "strace -ff -oLOG test/threaded_execve" corner case.
2243 * It's the only case when -ff mode needs reprinting.
2244 */
2245 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2246 tcp->flags &= ~TCB_REPRINT;
2247 printleader(tcp);
2248 if (!SCNO_IN_RANGE(tcp->scno))
2249 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2250 else
2251 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2252 }
2253 printing_tcp = tcp;
2254
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002255 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002256 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002257 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002258 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002259 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002260 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002261 tcp->flags &= ~TCB_INSYSCALL;
2262 return res;
2263 }
2264
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002265 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002266 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002267 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002268 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002269 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002270 /* FIXME: not_failing_only (IOW, option -z) is broken:
2271 * failure of syscall is known only after syscall return.
2272 * Thus we end up with something like this on, say, ENOENT:
2273 * open("doesnt_exist", O_RDONLY <unfinished ...>
2274 * {next syscall decode}
2275 * whereas the intended result is that open(...) line
2276 * is not shown at all.
2277 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002278 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002279 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002280 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2281 }
2282
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002283 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002284 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002285 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002286 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002287 qual_flags[tcp->scno] & QUAL_RAW) {
2288 if (u_error)
2289 tprintf("= -1 (errno %ld)", u_error);
2290 else
2291 tprintf("= %#lx", tcp->u_rval);
2292 }
2293 else if (!(sys_res & RVAL_NONE) && u_error) {
2294 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002295 /* Blocked signals do not interrupt any syscalls.
2296 * In this case syscalls don't return ERESTARTfoo codes.
2297 *
2298 * Deadly signals set to SIG_DFL interrupt syscalls
2299 * and kill the process regardless of which of the codes below
2300 * is returned by the interrupted syscall.
2301 * In some cases, kernel forces a kernel-generated deadly
2302 * signal to be unblocked and set to SIG_DFL (and thus cause
2303 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2304 * or SIGILL. (The alternative is to leave process spinning
2305 * forever on the faulty instruction - not useful).
2306 *
2307 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2308 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2309 * but kernel will always restart them.
2310 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002311 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002312 /* Most common type of signal-interrupted syscall exit code.
2313 * The system call will be restarted with the same arguments
2314 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2315 */
2316 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002317 break;
2318 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002319 /* Rare. For example, fork() returns this if interrupted.
2320 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2321 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002322 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002323 break;
2324 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002325 /* pause(), rt_sigsuspend() etc use this code.
2326 * SA_RESTART is ignored (assumed not set):
2327 * syscall won't restart (will return EINTR instead)
2328 * even after signal with SA_RESTART set.
2329 * However, after SIG_IGN or SIG_DFL signal it will.
2330 */
2331 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002332 break;
2333 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002334 /* Syscalls like nanosleep(), poll() which can't be
2335 * restarted with their original arguments use this
2336 * code. Kernel will execute restart_syscall() instead,
2337 * which changes arguments before restarting syscall.
2338 * SA_RESTART is ignored (assumed not set) similarly
2339 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2340 * since restart data is saved in "restart block"
2341 * in task struct, and if signal handler uses a syscall
2342 * which in turn saves another such restart block,
2343 * old data is lost and restart becomes impossible)
2344 */
2345 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002346 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002347 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002348 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002349 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002350 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002351 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002352 strerror(u_error));
2353 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002354 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002355 strerror(u_error));
2356 break;
2357 }
2358 if ((sys_res & RVAL_STR) && tcp->auxstr)
2359 tprintf(" (%s)", tcp->auxstr);
2360 }
2361 else {
2362 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002363 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002364 else {
2365 switch (sys_res & RVAL_MASK) {
2366 case RVAL_HEX:
2367 tprintf("= %#lx", tcp->u_rval);
2368 break;
2369 case RVAL_OCTAL:
2370 tprintf("= %#lo", tcp->u_rval);
2371 break;
2372 case RVAL_UDECIMAL:
2373 tprintf("= %lu", tcp->u_rval);
2374 break;
2375 case RVAL_DECIMAL:
2376 tprintf("= %ld", tcp->u_rval);
2377 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002378#if defined(LINUX_MIPSN32) || defined(X32)
2379 /*
2380 case RVAL_LHEX:
2381 tprintf("= %#llx", tcp->u_lrval);
2382 break;
2383 case RVAL_LOCTAL:
2384 tprintf("= %#llo", tcp->u_lrval);
2385 break;
2386 */
2387 case RVAL_LUDECIMAL:
2388 tprintf("= %llu", tcp->u_lrval);
2389 break;
2390 /*
2391 case RVAL_LDECIMAL:
2392 tprintf("= %lld", tcp->u_lrval);
2393 break;
2394 */
2395#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002396 default:
2397 fprintf(stderr,
2398 "invalid rval format\n");
2399 break;
2400 }
2401 }
2402 if ((sys_res & RVAL_STR) && tcp->auxstr)
2403 tprintf(" (%s)", tcp->auxstr);
2404 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002405 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002406 tv_sub(&tv, &tv, &tcp->etime);
2407 tprintf(" <%ld.%06ld>",
2408 (long) tv.tv_sec, (long) tv.tv_usec);
2409 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002410 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002411 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002412 line_ended();
2413
Denys Vlasenko3b738812011-08-22 02:06:35 +02002414 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002415 tcp->flags &= ~TCB_INSYSCALL;
2416 return 0;
2417}
2418
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002419int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002420trace_syscall(struct tcb *tcp)
2421{
2422 return exiting(tcp) ?
2423 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2424}