blob: 44964bccb6aec995f8e8c50759ffe898cedad965 [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
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000068#ifndef ERESTARTSYS
Denys Vlasenko523635f2012-02-25 02:44:25 +010069# define ERESTARTSYS 512
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000070#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010071#ifndef ERESTARTNOINTR
Denys Vlasenko523635f2012-02-25 02:44:25 +010072# define ERESTARTNOINTR 513
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000073#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010074#ifndef ERESTARTNOHAND
75# define ERESTARTNOHAND 514 /* restart if no handler */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000076#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010077#ifndef ERESTART_RESTARTBLOCK
Denys Vlasenko523635f2012-02-25 02:44:25 +010078# define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
Roland McGrath9c555e72003-07-09 09:47:59 +000079#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010080
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000081#ifndef NSIG
Denys Vlasenko523635f2012-02-25 02:44:25 +010082# warning: NSIG is not defined, using 32
83# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000084#endif
85#ifdef ARM
Denys Vlasenko041b3ee2011-08-18 12:48:56 +020086/* Ugh. Is this really correct? ARM has no RT signals?! */
Denys Vlasenko523635f2012-02-25 02:44:25 +010087# undef NSIG
88# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000089#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000090
91#include "syscall.h"
92
93/* Define these shorthand notations to simplify the syscallent files. */
Roland McGrath2fe7b132005-07-05 03:25:35 +000094#define TD TRACE_DESC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000095#define TF TRACE_FILE
96#define TI TRACE_IPC
97#define TN TRACE_NETWORK
98#define TP TRACE_PROCESS
99#define TS TRACE_SIGNAL
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000100#define NF SYSCALL_NEVER_FAILS
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200101#define MA MAX_ARGS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102
Roland McGrathee36ce12004-09-04 03:53:10 +0000103static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000104#include "syscallent.h"
105};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000106
107#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000108static const struct sysent sysent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100109# include "syscallent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000110};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200111#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000112
113#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000114static const struct sysent sysent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100115# include "syscallent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000116};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200117#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118
119/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000120#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121#undef TF
122#undef TI
123#undef TN
124#undef TP
125#undef TS
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000126#undef NF
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200127#undef MA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000128
Denys Vlasenko39fca622011-08-20 02:12:33 +0200129/*
130 * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
131 * program `ioctlsort', such that the list is sorted by the `code' field.
132 * This has the side-effect of resolving the _IO.. macros into
133 * plain integers, eliminating the need to include here everything
134 * in "/usr/include".
135 */
136
Roland McGrathee36ce12004-09-04 03:53:10 +0000137static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000138#include "errnoent.h"
139};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200140static const char *const signalent0[] = {
141#include "signalent.h"
142};
143static const struct ioctlent ioctlent0[] = {
144#include "ioctlent.h"
145};
146enum { nsyscalls0 = ARRAY_SIZE(sysent0) };
147enum { nerrnos0 = ARRAY_SIZE(errnoent0) };
148enum { nsignals0 = ARRAY_SIZE(signalent0) };
149enum { nioctlents0 = ARRAY_SIZE(ioctlent0) };
150int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000151
152#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000153static const char *const errnoent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100154# include "errnoent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000155};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200156static const char *const signalent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100157# include "signalent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200158};
159static const struct ioctlent ioctlent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100160# include "ioctlent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200161};
162enum { nsyscalls1 = ARRAY_SIZE(sysent1) };
163enum { nerrnos1 = ARRAY_SIZE(errnoent1) };
164enum { nsignals1 = ARRAY_SIZE(signalent1) };
165enum { nioctlents1 = ARRAY_SIZE(ioctlent1) };
166int qual_flags1[MAX_QUALS];
167#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000168
169#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000170static const char *const errnoent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100171# include "errnoent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000172};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200173static const char *const signalent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100174# include "signalent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200175};
176static const struct ioctlent ioctlent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100177# include "ioctlent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200178};
179enum { nsyscalls2 = ARRAY_SIZE(sysent2) };
180enum { nerrnos2 = ARRAY_SIZE(errnoent2) };
181enum { nsignals2 = ARRAY_SIZE(signalent2) };
182enum { nioctlents2 = ARRAY_SIZE(ioctlent2) };
183int qual_flags2[MAX_QUALS];
184#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000185
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100186const struct sysent *sysent = sysent0;
187const char *const *errnoent = errnoent0;
188const char *const *signalent = signalent0;
189const struct ioctlent *ioctlent = ioctlent0;
190unsigned nsyscalls = nsyscalls0;
191unsigned nerrnos = nerrnos0;
192unsigned nsignals = nsignals0;
193unsigned nioctlents = nioctlents0;
194int *qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000195
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100196#if SUPPORTED_PERSONALITIES > 1
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000197int current_personality;
198
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000199const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
200 PERSONALITY0_WORDSIZE,
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000201 PERSONALITY1_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100202# if SUPPORTED_PERSONALITIES > 2
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000203 PERSONALITY2_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100204# endif
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200205};
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000206
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200207void
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000208set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000209{
210 switch (personality) {
211 case 0:
212 errnoent = errnoent0;
213 nerrnos = nerrnos0;
214 sysent = sysent0;
215 nsyscalls = nsyscalls0;
216 ioctlent = ioctlent0;
217 nioctlents = nioctlents0;
218 signalent = signalent0;
219 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000220 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000221 break;
222
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000223 case 1:
224 errnoent = errnoent1;
225 nerrnos = nerrnos1;
226 sysent = sysent1;
227 nsyscalls = nsyscalls1;
228 ioctlent = ioctlent1;
229 nioctlents = nioctlents1;
230 signalent = signalent1;
231 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000232 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000233 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000234
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100235# if SUPPORTED_PERSONALITIES >= 3
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000236 case 2:
237 errnoent = errnoent2;
238 nerrnos = nerrnos2;
239 sysent = sysent2;
240 nsyscalls = nsyscalls2;
241 ioctlent = ioctlent2;
242 nioctlents = nioctlents2;
243 signalent = signalent2;
244 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000245 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000246 break;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100247# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000248 }
249
250 current_personality = personality;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000251}
252
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000253static void
254update_personality(struct tcb *tcp, int personality)
255{
256 if (personality == current_personality)
257 return;
258 set_personality(personality);
259
260 if (personality == tcp->currpers)
261 return;
262 tcp->currpers = personality;
263
H.J. Lu35be5812012-04-16 13:00:01 +0200264# if defined(POWERPC64)
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000265 if (!qflag) {
266 static const char *const names[] = {"64 bit", "32 bit"};
267 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
268 tcp->pid, names[personality]);
269 }
H.J. Lu35be5812012-04-16 13:00:01 +0200270# elif defined(X86_64)
271 if (!qflag) {
272 static const char *const names[] = {"64 bit", "32 bit", "x32"};
273 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
274 tcp->pid, names[personality]);
275 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100276# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000277}
278#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000279
Roland McGrath9797ceb2002-12-30 10:23:00 +0000280static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000281
Roland McGrathe10e62a2004-09-04 04:20:43 +0000282static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000283 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000284 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000285 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000286 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000287} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000288 { QUAL_TRACE, "trace", qual_syscall, "system call" },
289 { QUAL_TRACE, "t", qual_syscall, "system call" },
290 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
291 { QUAL_ABBREV, "a", qual_syscall, "system call" },
292 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
293 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
294 { QUAL_RAW, "raw", qual_syscall, "system call" },
295 { QUAL_RAW, "x", qual_syscall, "system call" },
296 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
297 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
298 { QUAL_SIGNAL, "s", qual_signal, "signal" },
299 { QUAL_FAULT, "fault", qual_fault, "fault" },
300 { QUAL_FAULT, "faults", qual_fault, "fault" },
301 { QUAL_FAULT, "m", qual_fault, "fault" },
302 { QUAL_READ, "read", qual_desc, "descriptor" },
303 { QUAL_READ, "reads", qual_desc, "descriptor" },
304 { QUAL_READ, "r", qual_desc, "descriptor" },
305 { QUAL_WRITE, "write", qual_desc, "descriptor" },
306 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
307 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000308 { 0, NULL, NULL, NULL },
309};
310
Roland McGrath9797ceb2002-12-30 10:23:00 +0000311static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000312qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000313{
Roland McGrath138c6a32006-01-12 09:50:49 +0000314 if (pers == 0 || pers < 0) {
315 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000316 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000317 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000318 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000319 }
320
321#if SUPPORTED_PERSONALITIES >= 2
322 if (pers == 1 || pers < 0) {
323 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000324 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000325 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000326 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000327 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100328#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000329
330#if SUPPORTED_PERSONALITIES >= 3
331 if (pers == 2 || pers < 0) {
332 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000333 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000334 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000335 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000336 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100337#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000338}
339
340static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000341qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000342{
343 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000344 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000345
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100346 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000347 int i = string_to_uint(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000348 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000349 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000350 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000351 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000352 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000353 for (i = 0; i < nsyscalls0; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000354 if (sysent0[i].sys_name &&
355 strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000356 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000357 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000358 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000359
360#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000361 for (i = 0; i < nsyscalls1; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000362 if (sysent1[i].sys_name &&
363 strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000364 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000365 rc = 0;
366 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100367#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000368
369#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000370 for (i = 0; i < nsyscalls2; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000371 if (sysent2[i].sys_name &&
372 strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000373 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000374 rc = 0;
375 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100376#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000377
Roland McGrathfe6b3522005-02-02 04:40:11 +0000378 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000379}
380
381static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000382qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000383{
384 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000385
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100386 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000387 int signo = string_to_uint(s);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000388 if (signo < 0 || signo >= MAX_QUALS)
389 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000390 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000391 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000392 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000393 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000394 s += 3;
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100395 for (i = 0; i <= NSIG; i++) {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000396 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000397 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000398 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000399 }
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100400 }
Roland McGrath76421df2005-02-02 03:51:18 +0000401 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000402}
403
404static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000405qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000406{
407 return -1;
408}
409
410static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000411qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000412{
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100413 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000414 int desc = string_to_uint(s);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000415 if (desc < 0 || desc >= MAX_QUALS)
416 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000417 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000418 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000419 }
420 return -1;
421}
422
423static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000424lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000425{
426 if (strcmp(s, "file") == 0)
427 return TRACE_FILE;
428 if (strcmp(s, "ipc") == 0)
429 return TRACE_IPC;
430 if (strcmp(s, "network") == 0)
431 return TRACE_NETWORK;
432 if (strcmp(s, "process") == 0)
433 return TRACE_PROCESS;
434 if (strcmp(s, "signal") == 0)
435 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000436 if (strcmp(s, "desc") == 0)
437 return TRACE_DESC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000438 return -1;
439}
440
441void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000442qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000443{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000444 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000445 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000446 char *copy;
447 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000448 int i, n;
449
450 opt = &qual_options[0];
451 for (i = 0; (p = qual_options[i].option_name); i++) {
452 n = strlen(p);
453 if (strncmp(s, p, n) == 0 && s[n] == '=') {
454 opt = &qual_options[i];
455 s += n + 1;
456 break;
457 }
458 }
459 not = 0;
460 if (*s == '!') {
461 not = 1;
462 s++;
463 }
464 if (strcmp(s, "none") == 0) {
465 not = 1 - not;
466 s = "all";
467 }
468 if (strcmp(s, "all") == 0) {
469 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000470 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000471 }
472 return;
473 }
474 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000475 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000476 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200477 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200478 if (!copy)
479 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000480 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000481 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000482 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000483 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000484 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000485
486#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000487 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000488 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000489 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100490#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000491
492#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000493 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000494 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000495 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100496#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000497
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000498 continue;
499 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000500 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100501 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000502 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000503 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000504 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000505 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000506 return;
507}
508
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000509#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000510static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000511decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000512{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000513 unsigned long addr;
514 unsigned int i, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000515
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000516 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
517 return;
518
519 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
520 addr = tcp->u_arg[1];
521 tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100522 size = current_wordsize;
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000523 for (i = 0; i < tcp->u_nargs; ++i) {
524 if (size == sizeof(int)) {
525 unsigned int arg;
526 if (umove(tcp, addr, &arg) < 0)
527 arg = 0;
528 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000529 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000530 else {
531 unsigned long arg;
532 if (umove(tcp, addr, &arg) < 0)
533 arg = 0;
534 tcp->u_arg[i] = arg;
535 }
536 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000537 }
538}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000539#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400540
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000541#ifdef SYS_ipc_subcall
542static void
543decode_ipc_subcall(struct tcb *tcp)
544{
545 unsigned int i;
546
547 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
548 return;
549
550 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
551 tcp->u_nargs = sysent[tcp->scno].nargs;
552 for (i = 0; i < tcp->u_nargs; i++)
553 tcp->u_arg[i] = tcp->u_arg[i + 1];
554}
555#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000556
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200557int
558printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000559{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200560 if (entering(tcp)) {
561 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000562
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200563 for (i = 0; i < tcp->u_nargs; i++)
564 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
565 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000566 return 0;
567}
568
Denys Vlasenko72879c62012-02-27 14:18:02 +0100569int
570printargs_lu(struct tcb *tcp)
571{
572 if (entering(tcp)) {
573 int i;
574
575 for (i = 0; i < tcp->u_nargs; i++)
576 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
577 }
578 return 0;
579}
580
581int
582printargs_ld(struct tcb *tcp)
583{
584 if (entering(tcp)) {
585 int i;
586
587 for (i = 0; i < tcp->u_nargs; i++)
588 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
589 }
590 return 0;
591}
592
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200593long
594getrval2(struct tcb *tcp)
595{
596 long val = -1;
597
Denys Vlasenko523635f2012-02-25 02:44:25 +0100598#if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200599 struct pt_regs regs;
600 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
601 return -1;
602 val = regs.u_regs[U_REG_O1];
603#elif defined(SH)
604 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
605 return -1;
606#elif defined(IA64)
607 if (upeek(tcp, PT_R9, &val) < 0)
608 return -1;
609#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200610
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200611 return val;
612}
613
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200614int
615is_restart_error(struct tcb *tcp)
616{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200617 switch (tcp->u_error) {
618 case ERESTARTSYS:
619 case ERESTARTNOINTR:
620 case ERESTARTNOHAND:
621 case ERESTART_RESTARTBLOCK:
622 return 1;
623 default:
624 break;
625 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200626 return 0;
627}
628
Denys Vlasenko523635f2012-02-25 02:44:25 +0100629#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100630struct pt_regs i386_regs;
H.J. Lu35be5812012-04-16 13:00:01 +0200631#elif defined(X86_64) || defined(X32)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100632/*
633 * On 32 bits, pt_regs and user_regs_struct are the same,
634 * but on 64 bits, user_regs_struct has six more fields:
635 * fs_base, gs_base, ds, es, fs, gs.
636 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
637 */
638static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100639#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200640long r8, r10, psr; /* TODO: make static? */
641long ia32 = 0; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100642#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +0100643static long ppc_result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100644#elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200645static long d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100646#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200647static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100648#elif defined(ARM)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200649static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100650#elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200651static long r0;
652static long a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100653#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200654static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100655#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200656static struct pt_regs regs;
657static unsigned long trap;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100658#elif defined(LINUX_MIPSN32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200659static long long a3;
660static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100661#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200662static long a3;
663static long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100664#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200665static long gpr2;
666static long pc;
667static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100668#elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200669static long r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100670#elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200671static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100672#elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200673static long r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100674#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200675static long r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100676#elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200677static long r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100678#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000679
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200680/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100681 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
682 * 1: ok, continue in trace_syscall_entering().
683 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200684 * ("????" etc) and bail out.
685 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100686static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200687get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000688{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000689 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000690
Denys Vlasenko523635f2012-02-25 02:44:25 +0100691#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000692 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200693 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000694
695 if (syscall_mode != -ENOSYS) {
696 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000697 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000698 */
699 scno = syscall_mode;
700 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000701 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000702 * Old style of "passing" the scno via the SVC instruction.
703 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000704 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200705 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200706 static const int gpr_offset[16] = {
707 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
708 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
709 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
710 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
711 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000712
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000713 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000714 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000715 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000716 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000717 if (errno) {
718 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000719 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000720 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000721
722 /*
723 * We have to check if the SVC got executed directly or via an
724 * EXECUTE instruction. In case of EXECUTE it is necessary to do
725 * instruction decoding to derive the system call number.
726 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
727 * so that this doesn't work if a SVC opcode is part of an EXECUTE
728 * opcode. Since there is no way to find out the opcode size this
729 * is the best we can do...
730 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000731 if ((opcode & 0xff00) == 0x0a00) {
732 /* SVC opcode */
733 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000734 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000735 else {
736 /* SVC got executed by EXECUTE instruction */
737
738 /*
739 * Do instruction decoding of EXECUTE. If you really want to
740 * understand this, read the Principles of Operations.
741 */
742 svc_addr = (void *) (opcode & 0xfff);
743
744 tmp = 0;
745 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000746 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000747 return -1;
748 svc_addr += tmp;
749
750 tmp = 0;
751 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000752 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000753 return -1;
754 svc_addr += tmp;
755
Denys Vlasenkofb036672009-01-23 16:30:26 +0000756 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000757 if (errno)
758 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100759# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000760 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100761# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000762 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100763# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000764 tmp = 0;
765 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000766 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000767 return -1;
768
769 scno = (scno | tmp) & 0xff;
770 }
771 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100772#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000773 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000774 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100775# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200776 /* TODO: speed up strace by not doing this at every syscall.
777 * We only need to do it after execve.
778 */
779 int currpers;
780 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200781
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200782 /* Check for 64/32 bit mode. */
783 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
784 return -1;
785 /* SF is bit 0 of MSR */
786 if (val < 0)
787 currpers = 0;
788 else
789 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000790 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100791# endif
792#elif defined(AVR32)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200793 /* Read complete register set in one go. */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000794 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
795 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200796 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100797#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000798 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000799 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100800#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200801 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000802 return -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200803 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +0200804#elif defined(X86_64) || defined(X32)
805# ifndef __X32_SYSCALL_BIT
806# define __X32_SYSCALL_BIT 0x40000000
807# endif
808# ifndef __X32_SYSCALL_MASK
809# define __X32_SYSCALL_MASK __X32_SYSCALL_BIT
810# endif
811
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200812 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200813 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
814 return -1;
815 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +0000816
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200817 /* Check CS register value. On x86-64 linux it is:
818 * 0x33 for long mode (64 bit)
819 * 0x23 for compatibility mode (32 bit)
H.J. Lu35be5812012-04-16 13:00:01 +0200820 * Check DS register value. On x86-64 linux it is:
821 * 0x2b for x32 mode (x86-64 in 32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200822 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200823 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200824 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +0200825 case 0x33:
826 if (x86_64_regs.ds == 0x2b) {
827 currpers = 2;
828 scno &= ~__X32_SYSCALL_MASK;
829 } else
830 currpers = 0;
831 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200832 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200833 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200834 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200835 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200836 currpers = current_personality;
837 break;
838 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100839# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200840 /* This version analyzes the opcode of a syscall instruction.
841 * (int 0x80 on i386 vs. syscall on x86-64)
842 * It works, but is too complicated.
843 */
844 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +0000845
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200846 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +0000847
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200848 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
849 rip -= 2;
850 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +0000851
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200852 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200853 if (errno)
854 fprintf(stderr, "ptrace_peektext failed: %s\n",
855 strerror(errno));
856 switch (call & 0xffff) {
857 /* x86-64: syscall = 0x0f 0x05 */
858 case 0x050f: currpers = 0; break;
859 /* i386: int 0x80 = 0xcd 0x80 */
860 case 0x80cd: currpers = 1; break;
861 default:
862 currpers = current_personality;
863 fprintf(stderr,
864 "Unknown syscall opcode (0x%04X) while "
865 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200866 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200867 break;
868 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100869# endif
H.J. Lu35be5812012-04-16 13:00:01 +0200870# ifdef X32
871 if (currpers == 0 || currpers == 1) {
872 fprintf(stderr, "syscall_%lu (...) in unsupported %s "
873 "mode of process PID=%d\n", scno,
874 currpers == 0 ? "64-bit" : "32-bit", tcp->pid);
875 return 0;
876 }
877# else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000878 update_personality(tcp, currpers);
H.J. Lu35be5812012-04-16 13:00:01 +0200879# endif
Denys Vlasenko523635f2012-02-25 02:44:25 +0100880#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000881# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200882 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000883 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200884 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200885 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200886 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000887 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200888 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000889 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200890 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100891#elif defined(ARM)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200892 /* Read complete register set in one go. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000893 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +0000894 return -1;
895
896 /*
897 * We only need to grab the syscall number on syscall entry.
898 */
899 if (regs.ARM_ip == 0) {
900 /*
901 * Note: we only deal with only 32-bit CPUs here.
902 */
903 if (regs.ARM_cpsr & 0x20) {
904 /*
905 * Get the Thumb-mode system call number
906 */
907 scno = regs.ARM_r7;
908 } else {
909 /*
910 * Get the ARM-mode system call number
911 */
912 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000913 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +0000914 if (errno)
915 return -1;
916
Roland McGrathf691bd22006-04-25 07:34:41 +0000917 /* Handle the EABI syscall convention. We do not
918 bother converting structures between the two
919 ABIs, but basic functionality should work even
920 if strace and the traced program have different
921 ABIs. */
922 if (scno == 0xef000000) {
923 scno = regs.ARM_r7;
924 } else {
925 if ((scno & 0x0ff00000) != 0x0f900000) {
926 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
927 scno);
928 return -1;
929 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000930
Roland McGrathf691bd22006-04-25 07:34:41 +0000931 /*
932 * Fixup the syscall number
933 */
934 scno &= 0x000fffff;
935 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000936 }
Roland McGrath56703312008-05-20 01:35:55 +0000937 if (scno & 0x0f0000) {
938 /*
939 * Handle ARM specific syscall
940 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000941 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +0000942 scno &= 0x0000ffff;
943 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000944 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +0000945
Roland McGrath0f87c492003-06-03 23:29:04 +0000946 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200947 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
948 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000949 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100950#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000951 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000952 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100953#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +0000954 unsigned long long regs[38];
955
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200956 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +0000957 return -1;
958 a3 = regs[REG_A3];
959 r2 = regs[REG_V0];
960
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200961 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200962 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200963 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100964 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200965 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000966 return 0;
967 }
Roland McGrath542c2c62008-05-20 01:11:56 +0000968 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100969#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000970 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000971 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200972 if (upeek(tcp, REG_V0, &scno) < 0)
973 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000974
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200975 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200976 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100977 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200978 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000979 return 0;
980 }
Wichert Akkermanf90da011999-10-31 21:15:38 +0000981 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100982#elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000983 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000984 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200985 if (upeek(tcp, REG_R0, &scno) < 0)
986 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000987
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200988 /*
989 * Do some sanity checks to figure out if it's
990 * really a syscall entry
991 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200992 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200993 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100994 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200995 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000996 return 0;
997 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000998 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100999#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001000 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001001 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001002 return -1;
1003
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001004 /* Disassemble the syscall trap. */
1005 /* Retrieve the syscall trap instruction. */
1006 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001007# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001008 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1009 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001010# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001011 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001012# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001013 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001014 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001015
1016 /* Disassemble the trap to see what personality to use. */
1017 switch (trap) {
1018 case 0x91d02010:
1019 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001020 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001021 break;
1022 case 0x91d0206d:
1023 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001024 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001025 break;
1026 case 0x91d02000:
1027 /* SunOS syscall trap. (pers 1) */
1028 fprintf(stderr, "syscall: SunOS no support\n");
1029 return -1;
1030 case 0x91d02008:
1031 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001032 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001033 break;
1034 case 0x91d02009:
1035 /* NetBSD/FreeBSD syscall trap. */
1036 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1037 return -1;
1038 case 0x91d02027:
1039 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001040 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001041 break;
1042 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001043# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001044 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001045# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001046 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001047# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001048 return -1;
1049 }
1050
1051 /* Extract the system call number from the registers. */
1052 if (trap == 0x91d02027)
1053 scno = 156;
1054 else
1055 scno = regs.u_regs[U_REG_G1];
1056 if (scno == 0) {
1057 scno = regs.u_regs[U_REG_O0];
1058 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1059 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001060#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001061 if (upeek(tcp, PT_GR20, &scno) < 0)
1062 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001063#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001064 /*
1065 * In the new syscall ABI, the system call number is in R3.
1066 */
1067 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1068 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001069
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001070 if (scno < 0) {
1071 /* Odd as it may seem, a glibc bug has been known to cause
1072 glibc to issue bogus negative syscall numbers. So for
1073 our purposes, make strace print what it *should* have been */
1074 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001075 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001076 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001077 "Detected glibc bug: bogus system call"
1078 " number = %ld, correcting to %ld\n",
1079 scno,
1080 correct_scno);
1081 scno = correct_scno;
1082 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001083#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001084 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001085 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001086 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001087#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001088 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1089 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001090#elif defined(TILE)
Chris Metcalfc8c66982009-12-28 10:00:15 -05001091 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1092 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001093#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001094 if (upeek(tcp, 0, &scno) < 0)
1095 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001096#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001097
Denys Vlasenko523635f2012-02-25 02:44:25 +01001098#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001099 /* new syscall ABI returns result in R0 */
1100 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1101 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001102#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001103 /* ABI defines result returned in r9 */
1104 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1105 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001106#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001107
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001108 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001109 return 1;
1110}
1111
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001112/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001113 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001114 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1115 * 1: ok, continue in trace_syscall_entering().
1116 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001117 * ("????" etc) and bail out.
1118 */
Roland McGratha4d48532005-06-08 20:45:28 +00001119static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001120syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001121{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001122 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001123#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001124 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001125 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001126 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1127 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001128 }
H.J. Lu35be5812012-04-16 13:00:01 +02001129#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001130 {
1131 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001132 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001133 rax = (int)rax; /* sign extend from 32 bits */
1134 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001135 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001136 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1137 return 0;
1138 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001139 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001140#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001141 /* TODO: we already fetched PT_GPR2 in get_scno
1142 * and stored it in syscall_mode, reuse it here
1143 * instead of re-fetching?
1144 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001145 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001146 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001147 if (syscall_mode != -ENOSYS)
1148 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001149 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001150 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001151 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001152 return 0;
1153 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001154#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001155 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001156 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001157 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001158 if (d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001159 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001160 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001161 return 0;
1162 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001163#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001164 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001165 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001166 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001167 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001168 if (ia32 && r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001169 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001170 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001171 return 0;
1172 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001173#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001174 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001175 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001176 if (r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001177 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001178 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001179 return 0;
1180 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001181#elif defined(MICROBLAZE)
1182 if (upeek(tcp, 3 * 4, &r3) < 0)
1183 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001184 if (r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001185 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001186 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001187 return 0;
1188 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001189#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001190 return 1;
1191}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001192
Denys Vlasenko146b9442012-03-18 22:10:48 +01001193static void
1194internal_fork(struct tcb *tcp)
1195{
1196#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1197# define ARG_FLAGS 1
1198#else
1199# define ARG_FLAGS 0
1200#endif
1201#ifndef CLONE_UNTRACED
1202# define CLONE_UNTRACED 0x00800000
1203#endif
1204 if ((ptrace_setoptions
1205 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1206 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1207 return;
1208
1209 if (!followfork)
1210 return;
1211
1212 if (entering(tcp)) {
1213 /*
1214 * We won't see the new child if clone is called with
1215 * CLONE_UNTRACED, so we keep the same logic with that option
1216 * and don't trace it.
1217 */
1218 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1219 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1220 return;
1221 setbpt(tcp);
1222 } else {
1223 if (tcp->flags & TCB_BPTSET)
1224 clearbpt(tcp);
1225 }
1226}
1227
1228#if defined(TCB_WAITEXECVE)
1229static void
1230internal_exec(struct tcb *tcp)
1231{
1232 /* Maybe we have post-execve SIGTRAP suppressed? */
1233 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1234 return; /* yes, no need to do anything */
1235
1236 if (exiting(tcp) && syserror(tcp))
1237 /* Error in execve, no post-execve SIGTRAP expected */
1238 tcp->flags &= ~TCB_WAITEXECVE;
1239 else
1240 tcp->flags |= TCB_WAITEXECVE;
1241}
1242#endif
1243
1244static void
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001245internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001246{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001247 /*
1248 * We must always trace a few critical system calls in order to
1249 * correctly support following forks in the presence of tracing
1250 * qualifiers.
1251 */
1252 int (*func)();
1253
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001254 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001255 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001256
1257 func = sysent[tcp->scno].sys_func;
1258
1259 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001260 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001261 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001262 ) {
1263 internal_fork(tcp);
1264 return;
1265 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001266
Denys Vlasenko84703742012-02-25 02:38:52 +01001267#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001268 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001269# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001270 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001271# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001272 ) {
1273 internal_exec(tcp);
1274 return;
1275 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001276#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001277}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001278
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001279/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001280static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001281get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001282{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001283 int i, nargs;
1284
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001285 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001286 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001287 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001288 nargs = tcp->u_nargs = MAX_ARGS;
1289
Denys Vlasenko523635f2012-02-25 02:44:25 +01001290#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001291 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001292 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1293 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001294#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001295 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001296 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1297 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001298#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001299 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001300 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001301 long rbs_end;
1302 /* be backwards compatible with kernel < 2.4.4... */
1303# ifndef PT_RBS_END
1304# define PT_RBS_END PT_AR_BSP
1305# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001306
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001307 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1308 return -1;
1309 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001310 return -1;
1311
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001312 sof = (cfm >> 0) & 0x7f;
1313 sol = (cfm >> 7) & 0x7f;
1314 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1315
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001316 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001317 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1318 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1319 return -1;
1320 }
1321 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001322 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1323 PT_R9 /* ECX = out1 */,
1324 PT_R10 /* EDX = out2 */,
1325 PT_R14 /* ESI = out3 */,
1326 PT_R15 /* EDI = out4 */,
1327 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001328
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001329 for (i = 0; i < nargs; ++i) {
1330 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1331 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001332 /* truncate away IVE sign-extension */
1333 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001334 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001335 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001336#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001337 /* N32 and N64 both use up to six registers. */
1338 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001339
1340 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1341 return -1;
1342
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001343 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001344 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001345# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001346 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001347# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001348 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001349#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001350 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001351 long sp;
1352
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001353 if (upeek(tcp, REG_SP, &sp) < 0)
1354 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001355 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001356 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1357 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001358 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001359 (char *)(tcp->u_arg + 4));
1360 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001361 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001362 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001363 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001364 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001365#elif defined(POWERPC)
1366# ifndef PT_ORIG_R3
1367# define PT_ORIG_R3 34
1368# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001369 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001370 if (upeek(tcp, (i==0) ?
1371 (sizeof(unsigned long) * PT_ORIG_R3) :
1372 ((i+PT_R3) * sizeof(unsigned long)),
1373 &tcp->u_arg[i]) < 0)
1374 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001375 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001376#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001377 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001378 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001379#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001380 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001381 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1382 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001383#elif defined(ARM)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001384 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001385 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001386#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001387 (void)i;
1388 (void)nargs;
1389 tcp->u_arg[0] = regs.r12;
1390 tcp->u_arg[1] = regs.r11;
1391 tcp->u_arg[2] = regs.r10;
1392 tcp->u_arg[3] = regs.r9;
1393 tcp->u_arg[4] = regs.r5;
1394 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001395#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001396 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 +02001397
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001398 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001399 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1400 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001401#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001402 static const int syscall_regs[MAX_ARGS] = {
1403 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1404 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001405 };
1406
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001407 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001408 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001409 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001410#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001411 int i;
1412 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001413 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001414
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001415 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001416 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1417 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001418#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001419 (void)i;
1420 (void)nargs;
H.J. Lu35be5812012-04-16 13:00:01 +02001421 if (current_personality != 1) { /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001422 tcp->u_arg[0] = x86_64_regs.rdi;
1423 tcp->u_arg[1] = x86_64_regs.rsi;
1424 tcp->u_arg[2] = x86_64_regs.rdx;
1425 tcp->u_arg[3] = x86_64_regs.r10;
1426 tcp->u_arg[4] = x86_64_regs.r8;
1427 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001428# ifdef X32
1429 tcp->ext_arg[0] = x86_64_regs.rdi;
1430 tcp->ext_arg[1] = x86_64_regs.rsi;
1431 tcp->ext_arg[2] = x86_64_regs.rdx;
1432 tcp->ext_arg[3] = x86_64_regs.r10;
1433 tcp->ext_arg[4] = x86_64_regs.r8;
1434 tcp->ext_arg[5] = x86_64_regs.r9;
1435# endif
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001436 } else { /* i386 ABI */
1437 /* Sign-extend lower 32 bits */
1438 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1439 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1440 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1441 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1442 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1443 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1444 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001445#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001446 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001447 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1448 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001449#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001450 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001451 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001452 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001453 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001454
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001455 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001456 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1457 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001458#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001459 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001460 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1461 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001462#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001463 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001464 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1465 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001466#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001467 (void)i;
1468 (void)nargs;
1469 tcp->u_arg[0] = i386_regs.ebx;
1470 tcp->u_arg[1] = i386_regs.ecx;
1471 tcp->u_arg[2] = i386_regs.edx;
1472 tcp->u_arg[3] = i386_regs.esi;
1473 tcp->u_arg[4] = i386_regs.edi;
1474 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001475#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001476 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001477 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1478 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001479#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001480 return 1;
1481}
1482
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001483static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001484trace_syscall_entering(struct tcb *tcp)
1485{
1486 int res, scno_good;
1487
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001488#if defined TCB_WAITEXECVE
1489 if (tcp->flags & TCB_WAITEXECVE) {
1490 /* This is the post-execve SIGTRAP. */
1491 tcp->flags &= ~TCB_WAITEXECVE;
1492 return 0;
1493 }
1494#endif
1495
Denys Vlasenko06602d92011-08-24 17:53:52 +02001496 scno_good = res = get_scno(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001497 if (res == 0)
1498 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001499 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001500 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001501 if (res == 0)
1502 return res;
1503 if (res == 1)
1504 res = get_syscall_args(tcp);
1505 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001506
1507 if (res != 1) {
1508 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001509 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001510 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001511 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001512 tprintf("syscall_%lu(", tcp->scno);
1513 else
1514 tprintf("%s(", sysent[tcp->scno].sys_name);
1515 /*
1516 * " <unavailable>" will be added later by the code which
1517 * detects ptrace errors.
1518 */
1519 goto ret;
1520 }
1521
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001522#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1523 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001524# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001525 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001526 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001527 break;
1528 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001529# endif
1530# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001531 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001532 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001533 break;
1534 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001535# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001536 break;
1537 }
1538#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1539
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001540 internal_syscall(tcp);
1541
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001542 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001543 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1544 (tracing_paths && !pathtrace_match(tcp))) {
1545 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1546 return 0;
1547 }
1548
1549 tcp->flags &= ~TCB_FILTERED;
1550
1551 if (cflag == CFLAG_ONLY_STATS) {
1552 res = 0;
1553 goto ret;
1554 }
1555
1556 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001557 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001558 tprintf("syscall_%lu(", tcp->scno);
1559 else
1560 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001561 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001562 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1563 sysent[tcp->scno].sys_func != sys_exit))
1564 res = printargs(tcp);
1565 else
1566 res = (*sysent[tcp->scno].sys_func)(tcp);
1567
1568 if (fflush(tcp->outf) == EOF)
1569 return -1;
1570 ret:
1571 tcp->flags |= TCB_INSYSCALL;
1572 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001573 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001574 gettimeofday(&tcp->etime, NULL);
1575 return res;
1576}
1577
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001578/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001579 * 1: ok, continue in trace_syscall_exiting().
1580 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001581 * ("????" etc) and bail out.
1582 */
1583static int
1584get_syscall_result(struct tcb *tcp)
1585{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001586#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001587 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1588 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001589#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001590# define SO_MASK 0x10000000
1591 {
1592 long flags;
1593 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1594 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001595 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001596 return -1;
1597 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001598 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001599 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001600#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001601 /* Read complete register set in one go. */
1602 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1603 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001604#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001605 if (upeek(tcp, PT_R0, &r0) < 0)
1606 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001607#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001608 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001609 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001610#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001611 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001612 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001613#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001614# define IA64_PSR_IS ((long)1 << 34)
1615 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1616 ia32 = (psr & IA64_PSR_IS) != 0;
1617 if (upeek(tcp, PT_R8, &r8) < 0)
1618 return -1;
1619 if (upeek(tcp, PT_R10, &r10) < 0)
1620 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001621#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001622 /* Read complete register set in one go. */
1623 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1624 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001625#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001626 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1627 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001628#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001629 unsigned long long regs[38];
1630
1631 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1632 return -1;
1633 a3 = regs[REG_A3];
1634 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001635#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001636 if (upeek(tcp, REG_A3, &a3) < 0)
1637 return -1;
1638 if (upeek(tcp, REG_V0, &r2) < 0)
1639 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001640#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001641 if (upeek(tcp, REG_A3, &a3) < 0)
1642 return -1;
1643 if (upeek(tcp, REG_R0, &r0) < 0)
1644 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001645#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001646 /* Everything we need is in the current register set. */
1647 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1648 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001649#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001650 if (upeek(tcp, PT_GR28, &r28) < 0)
1651 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001652#elif defined(SH)
1653#elif defined(SH64)
1654#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001655 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1656 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001657#elif defined(TILE)
1658#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001659 if (upeek(tcp, 3 * 4, &r3) < 0)
1660 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001661#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001662
Denys Vlasenko523635f2012-02-25 02:44:25 +01001663#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001664 /* new syscall ABI returns result in R0 */
1665 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1666 return -1;
1667#elif defined(SH64)
1668 /* ABI defines result returned in r9 */
1669 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1670 return -1;
1671#endif
1672
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001673 return 1;
1674}
1675
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001676/* Called at each syscall exit */
1677static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001678syscall_fixup_on_sysexit(struct tcb *tcp)
1679{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001680#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001681 if (syscall_mode != -ENOSYS)
1682 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001683 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001684 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1685 /*
1686 * Return from execve.
1687 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1688 * flag set for the post-execve SIGTRAP to see and reset.
1689 */
1690 gpr2 = 0;
1691 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001692#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001693}
1694
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001695/*
1696 * Check the syscall return value register value for whether it is
1697 * a negated errno code indicating an error, or a success return value.
1698 */
1699static inline int
1700is_negated_errno(unsigned long int val)
1701{
1702 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001703#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001704 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001705 val = (unsigned int) val;
1706 max = (unsigned int) max;
1707 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001708#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001709 return val > max;
1710}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001711
Denys Vlasenko907735a2012-03-21 00:23:16 +01001712/* Returns:
1713 * 1: ok, continue in trace_syscall_exiting().
1714 * -1: error, trace_syscall_exiting() should print error indicator
1715 * ("????" etc) and bail out.
1716 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001717static int
1718get_error(struct tcb *tcp)
1719{
1720 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001721 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001722 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001723 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1724 check_errno = 0;
1725 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001726#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001727 if (check_errno && is_negated_errno(gpr2)) {
1728 tcp->u_rval = -1;
1729 u_error = -gpr2;
1730 }
1731 else {
1732 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001733 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001734#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001735 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001736 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001737 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001738 }
1739 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001740 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001741 }
H.J. Lu35be5812012-04-16 13:00:01 +02001742#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001743 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001744 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001745 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001746 }
1747 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001748 tcp->u_rval = x86_64_regs.rax;
H.J. Lu35be5812012-04-16 13:00:01 +02001749# if defined(X32)
1750 tcp->u_lrval = x86_64_regs.rax;
1751# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001752 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001753#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001754 if (ia32) {
1755 int err;
1756
1757 err = (int)r8;
1758 if (check_errno && is_negated_errno(err)) {
1759 tcp->u_rval = -1;
1760 u_error = -err;
1761 }
1762 else {
1763 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001764 }
1765 } else {
1766 if (check_errno && r10) {
1767 tcp->u_rval = -1;
1768 u_error = r8;
1769 } else {
1770 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001771 }
1772 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001773#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001774 if (check_errno && a3) {
1775 tcp->u_rval = -1;
1776 u_error = r2;
1777 } else {
1778 tcp->u_rval = r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02001779# if defined(LINUX_MIPSN32)
1780 tcp->u_lrval = r2;
1781# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001782 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001783#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001784 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001785 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001786 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001787 }
1788 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001789 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001790 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001791#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001792 if (check_errno && is_negated_errno(d0)) {
1793 tcp->u_rval = -1;
1794 u_error = -d0;
1795 }
1796 else {
1797 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001798 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001799#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001800 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1801 tcp->u_rval = -1;
1802 u_error = -regs.ARM_r0;
1803 }
1804 else {
1805 tcp->u_rval = regs.ARM_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001806 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001807#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001808 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1809 tcp->u_rval = -1;
1810 u_error = -regs.r12;
1811 }
1812 else {
1813 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001814 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001815#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001816 if (check_errno && is_negated_errno(r0)) {
1817 tcp->u_rval = -1;
1818 u_error = -r0;
1819 } else {
1820 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001821 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001822#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001823 if (check_errno && a3) {
1824 tcp->u_rval = -1;
1825 u_error = r0;
1826 }
1827 else {
1828 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001829 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001830#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001831 if (check_errno && regs.psr & PSR_C) {
1832 tcp->u_rval = -1;
1833 u_error = regs.u_regs[U_REG_O0];
1834 }
1835 else {
1836 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001837 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001838#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001839 if (check_errno && regs.tstate & 0x1100000000UL) {
1840 tcp->u_rval = -1;
1841 u_error = regs.u_regs[U_REG_O0];
1842 }
1843 else {
1844 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001845 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001846#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001847 if (check_errno && is_negated_errno(r28)) {
1848 tcp->u_rval = -1;
1849 u_error = -r28;
1850 }
1851 else {
1852 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001853 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001854#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001855 if (check_errno && is_negated_errno(r0)) {
1856 tcp->u_rval = -1;
1857 u_error = -r0;
1858 }
1859 else {
1860 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001861 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001862#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001863 if (check_errno && is_negated_errno(r9)) {
1864 tcp->u_rval = -1;
1865 u_error = -r9;
1866 }
1867 else {
1868 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001869 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001870#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001871 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1872 tcp->u_rval = -1;
1873 u_error = -r10;
1874 }
1875 else {
1876 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001877 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001878#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001879 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001880 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1881 return -1;
1882 if (check_errno && rval < 0 && rval > -nerrnos) {
1883 tcp->u_rval = -1;
1884 u_error = -rval;
1885 }
1886 else {
1887 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001888 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001889#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001890 if (check_errno && is_negated_errno(r3)) {
1891 tcp->u_rval = -1;
1892 u_error = -r3;
1893 }
1894 else {
1895 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001896 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001897#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001898 tcp->u_error = u_error;
1899 return 1;
1900}
1901
1902static void
1903dumpio(struct tcb *tcp)
1904{
1905 if (syserror(tcp))
1906 return;
1907 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1908 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001909 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001910 return;
1911 if (sysent[tcp->scno].sys_func == printargs)
1912 return;
1913 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1914 if (sysent[tcp->scno].sys_func == sys_read ||
1915 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001916 sysent[tcp->scno].sys_func == sys_recv ||
1917 sysent[tcp->scno].sys_func == sys_recvfrom)
1918 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1919 else if (sysent[tcp->scno].sys_func == sys_readv)
1920 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1921 return;
1922 }
1923 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1924 if (sysent[tcp->scno].sys_func == sys_write ||
1925 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001926 sysent[tcp->scno].sys_func == sys_send ||
1927 sysent[tcp->scno].sys_func == sys_sendto)
1928 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1929 else if (sysent[tcp->scno].sys_func == sys_writev)
1930 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1931 return;
1932 }
1933}
1934
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001935static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001936trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001937{
1938 int sys_res;
1939 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001940 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001941 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001942
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001943 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001944 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001945 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001946
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001947#if SUPPORTED_PERSONALITIES > 1
1948 update_personality(tcp, tcp->currpers);
1949#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001950 res = get_syscall_result(tcp);
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001951 if (res == 1) {
1952 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01001953 res = get_error(tcp); /* returns 1 or -1 */
1954 if (res == 1) {
1955 internal_syscall(tcp);
1956 if (filtered(tcp)) {
1957 goto ret;
1958 }
1959 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00001960 }
1961
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001962 if (cflag) {
1963 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02001964 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02001965 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001966 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001967 }
1968 }
1969
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01001970 /* If not in -ff mode, and printing_tcp != tcp,
1971 * then the log currently does not end with output
1972 * of _our syscall entry_, but with something else.
1973 * We need to say which syscall's return is this.
1974 *
1975 * Forced reprinting via TCB_REPRINT is used only by
1976 * "strace -ff -oLOG test/threaded_execve" corner case.
1977 * It's the only case when -ff mode needs reprinting.
1978 */
1979 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
1980 tcp->flags &= ~TCB_REPRINT;
1981 printleader(tcp);
1982 if (!SCNO_IN_RANGE(tcp->scno))
1983 tprintf("<... syscall_%lu resumed> ", tcp->scno);
1984 else
1985 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
1986 }
1987 printing_tcp = tcp;
1988
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001989 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01001990 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001991 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001992 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01001993 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001994 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001995 tcp->flags &= ~TCB_INSYSCALL;
1996 return res;
1997 }
1998
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01001999 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002000 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002001 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002002 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002003 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002004 /* FIXME: not_failing_only (IOW, option -z) is broken:
2005 * failure of syscall is known only after syscall return.
2006 * Thus we end up with something like this on, say, ENOENT:
2007 * open("doesnt_exist", O_RDONLY <unfinished ...>
2008 * {next syscall decode}
2009 * whereas the intended result is that open(...) line
2010 * is not shown at all.
2011 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002012 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002013 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002014 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2015 }
2016
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002017 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002018 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002019 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002020 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002021 qual_flags[tcp->scno] & QUAL_RAW) {
2022 if (u_error)
2023 tprintf("= -1 (errno %ld)", u_error);
2024 else
2025 tprintf("= %#lx", tcp->u_rval);
2026 }
2027 else if (!(sys_res & RVAL_NONE) && u_error) {
2028 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002029 /* Blocked signals do not interrupt any syscalls.
2030 * In this case syscalls don't return ERESTARTfoo codes.
2031 *
2032 * Deadly signals set to SIG_DFL interrupt syscalls
2033 * and kill the process regardless of which of the codes below
2034 * is returned by the interrupted syscall.
2035 * In some cases, kernel forces a kernel-generated deadly
2036 * signal to be unblocked and set to SIG_DFL (and thus cause
2037 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2038 * or SIGILL. (The alternative is to leave process spinning
2039 * forever on the faulty instruction - not useful).
2040 *
2041 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2042 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2043 * but kernel will always restart them.
2044 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002045 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002046 /* Most common type of signal-interrupted syscall exit code.
2047 * The system call will be restarted with the same arguments
2048 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2049 */
2050 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002051 break;
2052 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002053 /* Rare. For example, fork() returns this if interrupted.
2054 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2055 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002056 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002057 break;
2058 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002059 /* pause(), rt_sigsuspend() etc use this code.
2060 * SA_RESTART is ignored (assumed not set):
2061 * syscall won't restart (will return EINTR instead)
2062 * even after signal with SA_RESTART set.
2063 * However, after SIG_IGN or SIG_DFL signal it will.
2064 */
2065 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002066 break;
2067 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002068 /* Syscalls like nanosleep(), poll() which can't be
2069 * restarted with their original arguments use this
2070 * code. Kernel will execute restart_syscall() instead,
2071 * which changes arguments before restarting syscall.
2072 * SA_RESTART is ignored (assumed not set) similarly
2073 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2074 * since restart data is saved in "restart block"
2075 * in task struct, and if signal handler uses a syscall
2076 * which in turn saves another such restart block,
2077 * old data is lost and restart becomes impossible)
2078 */
2079 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002080 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002081 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002082 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002083 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002084 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002085 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002086 strerror(u_error));
2087 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002088 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002089 strerror(u_error));
2090 break;
2091 }
2092 if ((sys_res & RVAL_STR) && tcp->auxstr)
2093 tprintf(" (%s)", tcp->auxstr);
2094 }
2095 else {
2096 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002097 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002098 else {
2099 switch (sys_res & RVAL_MASK) {
2100 case RVAL_HEX:
2101 tprintf("= %#lx", tcp->u_rval);
2102 break;
2103 case RVAL_OCTAL:
2104 tprintf("= %#lo", tcp->u_rval);
2105 break;
2106 case RVAL_UDECIMAL:
2107 tprintf("= %lu", tcp->u_rval);
2108 break;
2109 case RVAL_DECIMAL:
2110 tprintf("= %ld", tcp->u_rval);
2111 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002112#if defined(LINUX_MIPSN32) || defined(X32)
2113 /*
2114 case RVAL_LHEX:
2115 tprintf("= %#llx", tcp->u_lrval);
2116 break;
2117 case RVAL_LOCTAL:
2118 tprintf("= %#llo", tcp->u_lrval);
2119 break;
2120 */
2121 case RVAL_LUDECIMAL:
2122 tprintf("= %llu", tcp->u_lrval);
2123 break;
2124 /*
2125 case RVAL_LDECIMAL:
2126 tprintf("= %lld", tcp->u_lrval);
2127 break;
2128 */
2129#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002130 default:
2131 fprintf(stderr,
2132 "invalid rval format\n");
2133 break;
2134 }
2135 }
2136 if ((sys_res & RVAL_STR) && tcp->auxstr)
2137 tprintf(" (%s)", tcp->auxstr);
2138 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002139 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002140 tv_sub(&tv, &tv, &tcp->etime);
2141 tprintf(" <%ld.%06ld>",
2142 (long) tv.tv_sec, (long) tv.tv_usec);
2143 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002144 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002145 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002146 line_ended();
2147
Denys Vlasenko3b738812011-08-22 02:06:35 +02002148 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002149 tcp->flags &= ~TCB_INSYSCALL;
2150 return 0;
2151}
2152
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002153int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002154trace_syscall(struct tcb *tcp)
2155{
2156 return exiting(tcp) ?
2157 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2158}