blob: 7f3ff34667815fd00c2f806a7dca80d062e2649a [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
Denys Vlasenko523635f2012-02-25 02:44:25 +0100264# if defined(POWERPC64) || defined(X86_64)
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 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100270# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000271}
272#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000273
Roland McGrath9797ceb2002-12-30 10:23:00 +0000274static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000275
Roland McGrathe10e62a2004-09-04 04:20:43 +0000276static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000277 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000278 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000279 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000280 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000281} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000282 { QUAL_TRACE, "trace", qual_syscall, "system call" },
283 { QUAL_TRACE, "t", qual_syscall, "system call" },
284 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
285 { QUAL_ABBREV, "a", qual_syscall, "system call" },
286 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
287 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
288 { QUAL_RAW, "raw", qual_syscall, "system call" },
289 { QUAL_RAW, "x", qual_syscall, "system call" },
290 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
291 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
292 { QUAL_SIGNAL, "s", qual_signal, "signal" },
293 { QUAL_FAULT, "fault", qual_fault, "fault" },
294 { QUAL_FAULT, "faults", qual_fault, "fault" },
295 { QUAL_FAULT, "m", qual_fault, "fault" },
296 { QUAL_READ, "read", qual_desc, "descriptor" },
297 { QUAL_READ, "reads", qual_desc, "descriptor" },
298 { QUAL_READ, "r", qual_desc, "descriptor" },
299 { QUAL_WRITE, "write", qual_desc, "descriptor" },
300 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
301 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000302 { 0, NULL, NULL, NULL },
303};
304
Roland McGrath9797ceb2002-12-30 10:23:00 +0000305static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000306qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000307{
Roland McGrath138c6a32006-01-12 09:50:49 +0000308 if (pers == 0 || pers < 0) {
309 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000310 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000311 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000312 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000313 }
314
315#if SUPPORTED_PERSONALITIES >= 2
316 if (pers == 1 || pers < 0) {
317 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000318 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000319 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000320 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000321 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100322#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000323
324#if SUPPORTED_PERSONALITIES >= 3
325 if (pers == 2 || pers < 0) {
326 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000327 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000328 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000329 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000330 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100331#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000332}
333
334static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000335qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000336{
337 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000338 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000339
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100340 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000341 int i = string_to_uint(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000342 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000343 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000344 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000345 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000346 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000347 for (i = 0; i < nsyscalls0; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000348 if (sysent0[i].sys_name &&
349 strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000350 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000351 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000352 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000353
354#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000355 for (i = 0; i < nsyscalls1; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000356 if (sysent1[i].sys_name &&
357 strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000358 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000359 rc = 0;
360 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100361#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000362
363#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000364 for (i = 0; i < nsyscalls2; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000365 if (sysent2[i].sys_name &&
366 strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000367 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000368 rc = 0;
369 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100370#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000371
Roland McGrathfe6b3522005-02-02 04:40:11 +0000372 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000373}
374
375static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000376qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000377{
378 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000379
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100380 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000381 int signo = string_to_uint(s);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000382 if (signo < 0 || signo >= MAX_QUALS)
383 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000384 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000385 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000386 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000387 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000388 s += 3;
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100389 for (i = 0; i <= NSIG; i++) {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000390 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000391 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000392 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000393 }
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100394 }
Roland McGrath76421df2005-02-02 03:51:18 +0000395 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000396}
397
398static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000399qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000400{
401 return -1;
402}
403
404static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000405qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000406{
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100407 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000408 int desc = string_to_uint(s);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000409 if (desc < 0 || desc >= MAX_QUALS)
410 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000411 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000412 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000413 }
414 return -1;
415}
416
417static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000418lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000419{
420 if (strcmp(s, "file") == 0)
421 return TRACE_FILE;
422 if (strcmp(s, "ipc") == 0)
423 return TRACE_IPC;
424 if (strcmp(s, "network") == 0)
425 return TRACE_NETWORK;
426 if (strcmp(s, "process") == 0)
427 return TRACE_PROCESS;
428 if (strcmp(s, "signal") == 0)
429 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000430 if (strcmp(s, "desc") == 0)
431 return TRACE_DESC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000432 return -1;
433}
434
435void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000436qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000437{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000438 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000439 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000440 char *copy;
441 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000442 int i, n;
443
444 opt = &qual_options[0];
445 for (i = 0; (p = qual_options[i].option_name); i++) {
446 n = strlen(p);
447 if (strncmp(s, p, n) == 0 && s[n] == '=') {
448 opt = &qual_options[i];
449 s += n + 1;
450 break;
451 }
452 }
453 not = 0;
454 if (*s == '!') {
455 not = 1;
456 s++;
457 }
458 if (strcmp(s, "none") == 0) {
459 not = 1 - not;
460 s = "all";
461 }
462 if (strcmp(s, "all") == 0) {
463 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000464 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000465 }
466 return;
467 }
468 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000469 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000470 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200471 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200472 if (!copy)
473 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000474 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000475 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000476 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000477 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000478 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000479
480#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000481 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000482 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000483 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100484#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000485
486#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000487 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000488 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000489 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100490#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000491
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000492 continue;
493 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000494 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100495 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000496 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000497 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000498 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000499 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000500 return;
501}
502
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000503#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000504static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000505decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000506{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000507 unsigned long addr;
508 unsigned int i, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000509
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000510 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
511 return;
512
513 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
514 addr = tcp->u_arg[1];
515 tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100516 size = current_wordsize;
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000517 for (i = 0; i < tcp->u_nargs; ++i) {
518 if (size == sizeof(int)) {
519 unsigned int arg;
520 if (umove(tcp, addr, &arg) < 0)
521 arg = 0;
522 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000523 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000524 else {
525 unsigned long arg;
526 if (umove(tcp, addr, &arg) < 0)
527 arg = 0;
528 tcp->u_arg[i] = arg;
529 }
530 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000531 }
532}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000533#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400534
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000535#ifdef SYS_ipc_subcall
536static void
537decode_ipc_subcall(struct tcb *tcp)
538{
539 unsigned int i;
540
541 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
542 return;
543
544 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
545 tcp->u_nargs = sysent[tcp->scno].nargs;
546 for (i = 0; i < tcp->u_nargs; i++)
547 tcp->u_arg[i] = tcp->u_arg[i + 1];
548}
549#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000550
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200551int
552printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000553{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200554 if (entering(tcp)) {
555 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000556
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200557 for (i = 0; i < tcp->u_nargs; i++)
558 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
559 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000560 return 0;
561}
562
Denys Vlasenko72879c62012-02-27 14:18:02 +0100563int
564printargs_lu(struct tcb *tcp)
565{
566 if (entering(tcp)) {
567 int i;
568
569 for (i = 0; i < tcp->u_nargs; i++)
570 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
571 }
572 return 0;
573}
574
575int
576printargs_ld(struct tcb *tcp)
577{
578 if (entering(tcp)) {
579 int i;
580
581 for (i = 0; i < tcp->u_nargs; i++)
582 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
583 }
584 return 0;
585}
586
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200587long
588getrval2(struct tcb *tcp)
589{
590 long val = -1;
591
Denys Vlasenko523635f2012-02-25 02:44:25 +0100592#if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200593 struct pt_regs regs;
594 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
595 return -1;
596 val = regs.u_regs[U_REG_O1];
597#elif defined(SH)
598 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
599 return -1;
600#elif defined(IA64)
601 if (upeek(tcp, PT_R9, &val) < 0)
602 return -1;
603#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200604
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200605 return val;
606}
607
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200608int
609is_restart_error(struct tcb *tcp)
610{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200611 switch (tcp->u_error) {
612 case ERESTARTSYS:
613 case ERESTARTNOINTR:
614 case ERESTARTNOHAND:
615 case ERESTART_RESTARTBLOCK:
616 return 1;
617 default:
618 break;
619 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200620 return 0;
621}
622
Denys Vlasenko523635f2012-02-25 02:44:25 +0100623#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100624struct pt_regs i386_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100625#elif defined(X86_64)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100626/*
627 * On 32 bits, pt_regs and user_regs_struct are the same,
628 * but on 64 bits, user_regs_struct has six more fields:
629 * fs_base, gs_base, ds, es, fs, gs.
630 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
631 */
632static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100633#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200634long r8, r10, psr; /* TODO: make static? */
635long ia32 = 0; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100636#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +0100637static long ppc_result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100638#elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200639static long d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100640#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200641static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100642#elif defined(ARM)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200643static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100644#elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200645static long r0;
646static long a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100647#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200648static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100649#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200650static struct pt_regs regs;
651static unsigned long trap;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100652#elif defined(LINUX_MIPSN32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200653static long long a3;
654static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100655#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200656static long a3;
657static long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100658#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200659static long gpr2;
660static long pc;
661static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100662#elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200663static long r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100664#elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200665static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100666#elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200667static long r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100668#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200669static long r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100670#elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200671static long r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100672#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000673
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200674/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100675 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
676 * 1: ok, continue in trace_syscall_entering().
677 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200678 * ("????" etc) and bail out.
679 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100680static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200681get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000682{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000683 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000684
Denys Vlasenko523635f2012-02-25 02:44:25 +0100685#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000686 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200687 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000688
689 if (syscall_mode != -ENOSYS) {
690 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000691 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000692 */
693 scno = syscall_mode;
694 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000695 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000696 * Old style of "passing" the scno via the SVC instruction.
697 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000698 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200699 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200700 static const int gpr_offset[16] = {
701 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
702 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
703 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
704 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
705 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000706
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000707 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000708 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000709 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000710 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000711 if (errno) {
712 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000713 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000714 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000715
716 /*
717 * We have to check if the SVC got executed directly or via an
718 * EXECUTE instruction. In case of EXECUTE it is necessary to do
719 * instruction decoding to derive the system call number.
720 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
721 * so that this doesn't work if a SVC opcode is part of an EXECUTE
722 * opcode. Since there is no way to find out the opcode size this
723 * is the best we can do...
724 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000725 if ((opcode & 0xff00) == 0x0a00) {
726 /* SVC opcode */
727 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000728 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000729 else {
730 /* SVC got executed by EXECUTE instruction */
731
732 /*
733 * Do instruction decoding of EXECUTE. If you really want to
734 * understand this, read the Principles of Operations.
735 */
736 svc_addr = (void *) (opcode & 0xfff);
737
738 tmp = 0;
739 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000740 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000741 return -1;
742 svc_addr += tmp;
743
744 tmp = 0;
745 offset_reg = (opcode & 0x0000f000) >> 12;
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
Denys Vlasenkofb036672009-01-23 16:30:26 +0000750 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000751 if (errno)
752 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100753# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000754 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100755# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000756 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100757# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000758 tmp = 0;
759 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000760 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000761 return -1;
762
763 scno = (scno | tmp) & 0xff;
764 }
765 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100766#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000767 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000768 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100769# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200770 /* TODO: speed up strace by not doing this at every syscall.
771 * We only need to do it after execve.
772 */
773 int currpers;
774 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200775
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200776 /* Check for 64/32 bit mode. */
777 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
778 return -1;
779 /* SF is bit 0 of MSR */
780 if (val < 0)
781 currpers = 0;
782 else
783 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000784 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100785# endif
786#elif defined(AVR32)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200787 /* Read complete register set in one go. */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000788 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
789 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200790 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100791#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000792 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000793 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100794#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200795 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000796 return -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200797 scno = i386_regs.orig_eax;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100798#elif defined(X86_64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200799 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200800 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
801 return -1;
802 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +0000803
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200804 /* Check CS register value. On x86-64 linux it is:
805 * 0x33 for long mode (64 bit)
806 * 0x23 for compatibility mode (32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200807 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200808 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200809 case 0x23: currpers = 1; break;
810 case 0x33: currpers = 0; break;
811 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200812 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200813 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200814 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200815 currpers = current_personality;
816 break;
817 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100818# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200819 /* This version analyzes the opcode of a syscall instruction.
820 * (int 0x80 on i386 vs. syscall on x86-64)
821 * It works, but is too complicated.
822 */
823 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +0000824
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200825 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +0000826
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200827 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
828 rip -= 2;
829 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +0000830
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200831 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200832 if (errno)
833 fprintf(stderr, "ptrace_peektext failed: %s\n",
834 strerror(errno));
835 switch (call & 0xffff) {
836 /* x86-64: syscall = 0x0f 0x05 */
837 case 0x050f: currpers = 0; break;
838 /* i386: int 0x80 = 0xcd 0x80 */
839 case 0x80cd: currpers = 1; break;
840 default:
841 currpers = current_personality;
842 fprintf(stderr,
843 "Unknown syscall opcode (0x%04X) while "
844 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200845 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200846 break;
847 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100848# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000849 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100850#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000851# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200852 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000853 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200854 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200855 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200856 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000857 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200858 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000859 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200860 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100861#elif defined(ARM)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200862 /* Read complete register set in one go. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000863 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +0000864 return -1;
865
866 /*
867 * We only need to grab the syscall number on syscall entry.
868 */
869 if (regs.ARM_ip == 0) {
870 /*
871 * Note: we only deal with only 32-bit CPUs here.
872 */
873 if (regs.ARM_cpsr & 0x20) {
874 /*
875 * Get the Thumb-mode system call number
876 */
877 scno = regs.ARM_r7;
878 } else {
879 /*
880 * Get the ARM-mode system call number
881 */
882 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000883 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +0000884 if (errno)
885 return -1;
886
Roland McGrathf691bd22006-04-25 07:34:41 +0000887 /* Handle the EABI syscall convention. We do not
888 bother converting structures between the two
889 ABIs, but basic functionality should work even
890 if strace and the traced program have different
891 ABIs. */
892 if (scno == 0xef000000) {
893 scno = regs.ARM_r7;
894 } else {
895 if ((scno & 0x0ff00000) != 0x0f900000) {
896 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
897 scno);
898 return -1;
899 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000900
Roland McGrathf691bd22006-04-25 07:34:41 +0000901 /*
902 * Fixup the syscall number
903 */
904 scno &= 0x000fffff;
905 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000906 }
Roland McGrath56703312008-05-20 01:35:55 +0000907 if (scno & 0x0f0000) {
908 /*
909 * Handle ARM specific syscall
910 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000911 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +0000912 scno &= 0x0000ffff;
913 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000914 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +0000915
Roland McGrath0f87c492003-06-03 23:29:04 +0000916 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200917 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
918 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000919 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100920#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000921 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000922 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100923#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +0000924 unsigned long long regs[38];
925
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200926 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +0000927 return -1;
928 a3 = regs[REG_A3];
929 r2 = regs[REG_V0];
930
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200931 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200932 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200933 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100934 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200935 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000936 return 0;
937 }
Roland McGrath542c2c62008-05-20 01:11:56 +0000938 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100939#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000940 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000941 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200942 if (upeek(tcp, REG_V0, &scno) < 0)
943 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000944
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200945 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200946 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100947 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200948 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000949 return 0;
950 }
Wichert Akkermanf90da011999-10-31 21:15:38 +0000951 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100952#elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000953 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000954 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200955 if (upeek(tcp, REG_R0, &scno) < 0)
956 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000957
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200958 /*
959 * Do some sanity checks to figure out if it's
960 * really a syscall entry
961 */
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: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000966 return 0;
967 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000968 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100969#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000970 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000971 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000972 return -1;
973
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200974 /* Disassemble the syscall trap. */
975 /* Retrieve the syscall trap instruction. */
976 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100977# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200978 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
979 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100980# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200981 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100982# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200983 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +0000984 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200985
986 /* Disassemble the trap to see what personality to use. */
987 switch (trap) {
988 case 0x91d02010:
989 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000990 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200991 break;
992 case 0x91d0206d:
993 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000994 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200995 break;
996 case 0x91d02000:
997 /* SunOS syscall trap. (pers 1) */
998 fprintf(stderr, "syscall: SunOS no support\n");
999 return -1;
1000 case 0x91d02008:
1001 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001002 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001003 break;
1004 case 0x91d02009:
1005 /* NetBSD/FreeBSD syscall trap. */
1006 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1007 return -1;
1008 case 0x91d02027:
1009 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001010 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001011 break;
1012 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001013# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001014 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001015# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001016 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001017# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001018 return -1;
1019 }
1020
1021 /* Extract the system call number from the registers. */
1022 if (trap == 0x91d02027)
1023 scno = 156;
1024 else
1025 scno = regs.u_regs[U_REG_G1];
1026 if (scno == 0) {
1027 scno = regs.u_regs[U_REG_O0];
1028 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1029 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001030#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001031 if (upeek(tcp, PT_GR20, &scno) < 0)
1032 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001033#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001034 /*
1035 * In the new syscall ABI, the system call number is in R3.
1036 */
1037 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1038 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001039
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001040 if (scno < 0) {
1041 /* Odd as it may seem, a glibc bug has been known to cause
1042 glibc to issue bogus negative syscall numbers. So for
1043 our purposes, make strace print what it *should* have been */
1044 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001045 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001046 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001047 "Detected glibc bug: bogus system call"
1048 " number = %ld, correcting to %ld\n",
1049 scno,
1050 correct_scno);
1051 scno = correct_scno;
1052 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001053#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001054 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001055 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001056 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001057#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001058 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1059 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001060#elif defined(TILE)
Chris Metcalfc8c66982009-12-28 10:00:15 -05001061 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1062 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001063#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001064 if (upeek(tcp, 0, &scno) < 0)
1065 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001066#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001067
Denys Vlasenko523635f2012-02-25 02:44:25 +01001068#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001069 /* new syscall ABI returns result in R0 */
1070 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1071 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001072#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001073 /* ABI defines result returned in r9 */
1074 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1075 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001076#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001077
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001078 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001079 return 1;
1080}
1081
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001082/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001083 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001084 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1085 * 1: ok, continue in trace_syscall_entering().
1086 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001087 * ("????" etc) and bail out.
1088 */
Roland McGratha4d48532005-06-08 20:45:28 +00001089static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001090syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001091{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001092 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001093#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001094 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001095 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001096 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1097 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001098 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001099#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001100 {
1101 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001102 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001103 rax = (int)rax; /* sign extend from 32 bits */
1104 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001105 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001106 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1107 return 0;
1108 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001109 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001110#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001111 /* TODO: we already fetched PT_GPR2 in get_scno
1112 * and stored it in syscall_mode, reuse it here
1113 * instead of re-fetching?
1114 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001115 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001116 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001117 if (syscall_mode != -ENOSYS)
1118 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001119 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001120 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001121 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001122 return 0;
1123 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001124#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001125 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001126 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001127 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001128 if (d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001129 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001130 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001131 return 0;
1132 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001133#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001134 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001135 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001136 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001137 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001138 if (ia32 && r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001139 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001140 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001141 return 0;
1142 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001143#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001144 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001145 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001146 if (r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001147 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001148 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001149 return 0;
1150 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001151#elif defined(MICROBLAZE)
1152 if (upeek(tcp, 3 * 4, &r3) < 0)
1153 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001154 if (r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001155 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001156 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001157 return 0;
1158 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001159#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001160 return 1;
1161}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001162
Denys Vlasenko146b9442012-03-18 22:10:48 +01001163static void
1164internal_fork(struct tcb *tcp)
1165{
1166#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1167# define ARG_FLAGS 1
1168#else
1169# define ARG_FLAGS 0
1170#endif
1171#ifndef CLONE_UNTRACED
1172# define CLONE_UNTRACED 0x00800000
1173#endif
1174 if ((ptrace_setoptions
1175 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1176 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1177 return;
1178
1179 if (!followfork)
1180 return;
1181
1182 if (entering(tcp)) {
1183 /*
1184 * We won't see the new child if clone is called with
1185 * CLONE_UNTRACED, so we keep the same logic with that option
1186 * and don't trace it.
1187 */
1188 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1189 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1190 return;
1191 setbpt(tcp);
1192 } else {
1193 if (tcp->flags & TCB_BPTSET)
1194 clearbpt(tcp);
1195 }
1196}
1197
1198#if defined(TCB_WAITEXECVE)
1199static void
1200internal_exec(struct tcb *tcp)
1201{
1202 /* Maybe we have post-execve SIGTRAP suppressed? */
1203 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1204 return; /* yes, no need to do anything */
1205
1206 if (exiting(tcp) && syserror(tcp))
1207 /* Error in execve, no post-execve SIGTRAP expected */
1208 tcp->flags &= ~TCB_WAITEXECVE;
1209 else
1210 tcp->flags |= TCB_WAITEXECVE;
1211}
1212#endif
1213
1214static void
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001215internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001216{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001217 /*
1218 * We must always trace a few critical system calls in order to
1219 * correctly support following forks in the presence of tracing
1220 * qualifiers.
1221 */
1222 int (*func)();
1223
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001224 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001225 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001226
1227 func = sysent[tcp->scno].sys_func;
1228
1229 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001230 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001231 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001232 ) {
1233 internal_fork(tcp);
1234 return;
1235 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001236
Denys Vlasenko84703742012-02-25 02:38:52 +01001237#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001238 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001239# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001240 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001241# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001242 ) {
1243 internal_exec(tcp);
1244 return;
1245 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001246#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001247}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001248
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001249/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001250static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001251get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001252{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001253 int i, nargs;
1254
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001255 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001256 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001257 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001258 nargs = tcp->u_nargs = MAX_ARGS;
1259
Denys Vlasenko523635f2012-02-25 02:44:25 +01001260#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001261 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001262 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1263 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001264#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001265 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001266 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1267 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001268#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001269 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001270 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001271 long rbs_end;
1272 /* be backwards compatible with kernel < 2.4.4... */
1273# ifndef PT_RBS_END
1274# define PT_RBS_END PT_AR_BSP
1275# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001276
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001277 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1278 return -1;
1279 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001280 return -1;
1281
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001282 sof = (cfm >> 0) & 0x7f;
1283 sol = (cfm >> 7) & 0x7f;
1284 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1285
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001286 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001287 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1288 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1289 return -1;
1290 }
1291 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001292 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1293 PT_R9 /* ECX = out1 */,
1294 PT_R10 /* EDX = out2 */,
1295 PT_R14 /* ESI = out3 */,
1296 PT_R15 /* EDI = out4 */,
1297 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001298
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001299 for (i = 0; i < nargs; ++i) {
1300 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1301 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001302 /* truncate away IVE sign-extension */
1303 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001304 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001305 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001306#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001307 /* N32 and N64 both use up to six registers. */
1308 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001309
1310 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1311 return -1;
1312
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001313 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001314 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001315# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001316 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001317# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001318 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001319#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001320 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001321 long sp;
1322
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001323 if (upeek(tcp, REG_SP, &sp) < 0)
1324 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001325 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001326 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1327 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001328 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001329 (char *)(tcp->u_arg + 4));
1330 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001331 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001332 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001333 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001334 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001335#elif defined(POWERPC)
1336# ifndef PT_ORIG_R3
1337# define PT_ORIG_R3 34
1338# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001339 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001340 if (upeek(tcp, (i==0) ?
1341 (sizeof(unsigned long) * PT_ORIG_R3) :
1342 ((i+PT_R3) * sizeof(unsigned long)),
1343 &tcp->u_arg[i]) < 0)
1344 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001345 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001346#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001347 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001348 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001349#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001350 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001351 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1352 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001353#elif defined(ARM)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001354 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001355 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001356#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001357 (void)i;
1358 (void)nargs;
1359 tcp->u_arg[0] = regs.r12;
1360 tcp->u_arg[1] = regs.r11;
1361 tcp->u_arg[2] = regs.r10;
1362 tcp->u_arg[3] = regs.r9;
1363 tcp->u_arg[4] = regs.r5;
1364 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001365#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001366 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 +02001367
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001368 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001369 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1370 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001371#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001372 static const int syscall_regs[MAX_ARGS] = {
1373 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1374 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001375 };
1376
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001377 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001378 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001379 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001380#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001381 int i;
1382 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001383 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001384
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001385 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001386 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1387 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001388#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001389 (void)i;
1390 (void)nargs;
1391 if (current_personality == 0) { /* x86-64 ABI */
1392 tcp->u_arg[0] = x86_64_regs.rdi;
1393 tcp->u_arg[1] = x86_64_regs.rsi;
1394 tcp->u_arg[2] = x86_64_regs.rdx;
1395 tcp->u_arg[3] = x86_64_regs.r10;
1396 tcp->u_arg[4] = x86_64_regs.r8;
1397 tcp->u_arg[5] = x86_64_regs.r9;
1398 } else { /* i386 ABI */
1399 /* Sign-extend lower 32 bits */
1400 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1401 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1402 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1403 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1404 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1405 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1406 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001407#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001408 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001409 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1410 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001411#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001412 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001413 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001414 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001415 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001416
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001417 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001418 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1419 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001420#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001421 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001422 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1423 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001424#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001425 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001426 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1427 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001428#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001429 (void)i;
1430 (void)nargs;
1431 tcp->u_arg[0] = i386_regs.ebx;
1432 tcp->u_arg[1] = i386_regs.ecx;
1433 tcp->u_arg[2] = i386_regs.edx;
1434 tcp->u_arg[3] = i386_regs.esi;
1435 tcp->u_arg[4] = i386_regs.edi;
1436 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001437#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001438 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001439 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1440 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001441#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001442 return 1;
1443}
1444
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001445static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001446trace_syscall_entering(struct tcb *tcp)
1447{
1448 int res, scno_good;
1449
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001450#if defined TCB_WAITEXECVE
1451 if (tcp->flags & TCB_WAITEXECVE) {
1452 /* This is the post-execve SIGTRAP. */
1453 tcp->flags &= ~TCB_WAITEXECVE;
1454 return 0;
1455 }
1456#endif
1457
Denys Vlasenko06602d92011-08-24 17:53:52 +02001458 scno_good = res = get_scno(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001459 if (res == 0)
1460 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001461 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001462 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001463 if (res == 0)
1464 return res;
1465 if (res == 1)
1466 res = get_syscall_args(tcp);
1467 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001468
1469 if (res != 1) {
1470 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001471 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001472 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001473 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001474 tprintf("syscall_%lu(", tcp->scno);
1475 else
1476 tprintf("%s(", sysent[tcp->scno].sys_name);
1477 /*
1478 * " <unavailable>" will be added later by the code which
1479 * detects ptrace errors.
1480 */
1481 goto ret;
1482 }
1483
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001484#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1485 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001486# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001487 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001488 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001489 break;
1490 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001491# endif
1492# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001493 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001494 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001495 break;
1496 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001497# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001498 break;
1499 }
1500#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1501
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001502 internal_syscall(tcp);
1503
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001504 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001505 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1506 (tracing_paths && !pathtrace_match(tcp))) {
1507 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1508 return 0;
1509 }
1510
1511 tcp->flags &= ~TCB_FILTERED;
1512
1513 if (cflag == CFLAG_ONLY_STATS) {
1514 res = 0;
1515 goto ret;
1516 }
1517
1518 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001519 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001520 tprintf("syscall_%lu(", tcp->scno);
1521 else
1522 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001523 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001524 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1525 sysent[tcp->scno].sys_func != sys_exit))
1526 res = printargs(tcp);
1527 else
1528 res = (*sysent[tcp->scno].sys_func)(tcp);
1529
1530 if (fflush(tcp->outf) == EOF)
1531 return -1;
1532 ret:
1533 tcp->flags |= TCB_INSYSCALL;
1534 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001535 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001536 gettimeofday(&tcp->etime, NULL);
1537 return res;
1538}
1539
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001540/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001541 * 1: ok, continue in trace_syscall_exiting().
1542 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001543 * ("????" etc) and bail out.
1544 */
1545static int
1546get_syscall_result(struct tcb *tcp)
1547{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001548#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001549 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1550 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001551#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001552# define SO_MASK 0x10000000
1553 {
1554 long flags;
1555 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1556 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001557 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001558 return -1;
1559 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001560 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001561 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001562#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001563 /* Read complete register set in one go. */
1564 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1565 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001566#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001567 if (upeek(tcp, PT_R0, &r0) < 0)
1568 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001569#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001570 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001571 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001572#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001573 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001574 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001575#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001576# define IA64_PSR_IS ((long)1 << 34)
1577 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1578 ia32 = (psr & IA64_PSR_IS) != 0;
1579 if (upeek(tcp, PT_R8, &r8) < 0)
1580 return -1;
1581 if (upeek(tcp, PT_R10, &r10) < 0)
1582 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001583#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001584 /* Read complete register set in one go. */
1585 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1586 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001587#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001588 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1589 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001590#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001591 unsigned long long regs[38];
1592
1593 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1594 return -1;
1595 a3 = regs[REG_A3];
1596 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001597#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001598 if (upeek(tcp, REG_A3, &a3) < 0)
1599 return -1;
1600 if (upeek(tcp, REG_V0, &r2) < 0)
1601 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001602#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001603 if (upeek(tcp, REG_A3, &a3) < 0)
1604 return -1;
1605 if (upeek(tcp, REG_R0, &r0) < 0)
1606 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001607#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001608 /* Everything we need is in the current register set. */
1609 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1610 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001611#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001612 if (upeek(tcp, PT_GR28, &r28) < 0)
1613 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001614#elif defined(SH)
1615#elif defined(SH64)
1616#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001617 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1618 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001619#elif defined(TILE)
1620#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001621 if (upeek(tcp, 3 * 4, &r3) < 0)
1622 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001623#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001624
Denys Vlasenko523635f2012-02-25 02:44:25 +01001625#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001626 /* new syscall ABI returns result in R0 */
1627 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1628 return -1;
1629#elif defined(SH64)
1630 /* ABI defines result returned in r9 */
1631 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1632 return -1;
1633#endif
1634
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001635 return 1;
1636}
1637
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001638/* Called at each syscall exit */
1639static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001640syscall_fixup_on_sysexit(struct tcb *tcp)
1641{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001642#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001643 if (syscall_mode != -ENOSYS)
1644 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001645 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001646 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1647 /*
1648 * Return from execve.
1649 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1650 * flag set for the post-execve SIGTRAP to see and reset.
1651 */
1652 gpr2 = 0;
1653 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001654#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001655}
1656
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001657/*
1658 * Check the syscall return value register value for whether it is
1659 * a negated errno code indicating an error, or a success return value.
1660 */
1661static inline int
1662is_negated_errno(unsigned long int val)
1663{
1664 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001665#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001666 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001667 val = (unsigned int) val;
1668 max = (unsigned int) max;
1669 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001670#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001671 return val > max;
1672}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001673
Denys Vlasenko907735a2012-03-21 00:23:16 +01001674/* Returns:
1675 * 1: ok, continue in trace_syscall_exiting().
1676 * -1: error, trace_syscall_exiting() should print error indicator
1677 * ("????" etc) and bail out.
1678 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001679static int
1680get_error(struct tcb *tcp)
1681{
1682 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001683 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001684 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001685 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1686 check_errno = 0;
1687 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001688#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001689 if (check_errno && is_negated_errno(gpr2)) {
1690 tcp->u_rval = -1;
1691 u_error = -gpr2;
1692 }
1693 else {
1694 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001695 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001696#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001697 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001698 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001699 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001700 }
1701 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001702 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001703 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001704#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001705 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001706 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001707 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001708 }
1709 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001710 tcp->u_rval = x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001711 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001712#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001713 if (ia32) {
1714 int err;
1715
1716 err = (int)r8;
1717 if (check_errno && is_negated_errno(err)) {
1718 tcp->u_rval = -1;
1719 u_error = -err;
1720 }
1721 else {
1722 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001723 }
1724 } else {
1725 if (check_errno && r10) {
1726 tcp->u_rval = -1;
1727 u_error = r8;
1728 } else {
1729 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001730 }
1731 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001732#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001733 if (check_errno && a3) {
1734 tcp->u_rval = -1;
1735 u_error = r2;
1736 } else {
1737 tcp->u_rval = r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02001738# if defined(LINUX_MIPSN32)
1739 tcp->u_lrval = r2;
1740# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001741 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001742#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001743 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001744 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001745 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001746 }
1747 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001748 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001749 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001750#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001751 if (check_errno && is_negated_errno(d0)) {
1752 tcp->u_rval = -1;
1753 u_error = -d0;
1754 }
1755 else {
1756 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001757 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001758#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001759 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1760 tcp->u_rval = -1;
1761 u_error = -regs.ARM_r0;
1762 }
1763 else {
1764 tcp->u_rval = regs.ARM_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001765 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001766#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001767 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1768 tcp->u_rval = -1;
1769 u_error = -regs.r12;
1770 }
1771 else {
1772 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001773 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001774#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001775 if (check_errno && is_negated_errno(r0)) {
1776 tcp->u_rval = -1;
1777 u_error = -r0;
1778 } else {
1779 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001780 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001781#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001782 if (check_errno && a3) {
1783 tcp->u_rval = -1;
1784 u_error = r0;
1785 }
1786 else {
1787 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001788 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001789#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001790 if (check_errno && regs.psr & PSR_C) {
1791 tcp->u_rval = -1;
1792 u_error = regs.u_regs[U_REG_O0];
1793 }
1794 else {
1795 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001796 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001797#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001798 if (check_errno && regs.tstate & 0x1100000000UL) {
1799 tcp->u_rval = -1;
1800 u_error = regs.u_regs[U_REG_O0];
1801 }
1802 else {
1803 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001804 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001805#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001806 if (check_errno && is_negated_errno(r28)) {
1807 tcp->u_rval = -1;
1808 u_error = -r28;
1809 }
1810 else {
1811 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001812 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001813#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001814 if (check_errno && is_negated_errno(r0)) {
1815 tcp->u_rval = -1;
1816 u_error = -r0;
1817 }
1818 else {
1819 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001820 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001821#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001822 if (check_errno && is_negated_errno(r9)) {
1823 tcp->u_rval = -1;
1824 u_error = -r9;
1825 }
1826 else {
1827 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001828 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001829#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001830 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1831 tcp->u_rval = -1;
1832 u_error = -r10;
1833 }
1834 else {
1835 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001836 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001837#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001838 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001839 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1840 return -1;
1841 if (check_errno && rval < 0 && rval > -nerrnos) {
1842 tcp->u_rval = -1;
1843 u_error = -rval;
1844 }
1845 else {
1846 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001847 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001848#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001849 if (check_errno && is_negated_errno(r3)) {
1850 tcp->u_rval = -1;
1851 u_error = -r3;
1852 }
1853 else {
1854 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001855 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001856#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001857 tcp->u_error = u_error;
1858 return 1;
1859}
1860
1861static void
1862dumpio(struct tcb *tcp)
1863{
1864 if (syserror(tcp))
1865 return;
1866 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1867 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001868 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001869 return;
1870 if (sysent[tcp->scno].sys_func == printargs)
1871 return;
1872 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1873 if (sysent[tcp->scno].sys_func == sys_read ||
1874 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001875 sysent[tcp->scno].sys_func == sys_recv ||
1876 sysent[tcp->scno].sys_func == sys_recvfrom)
1877 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1878 else if (sysent[tcp->scno].sys_func == sys_readv)
1879 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1880 return;
1881 }
1882 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1883 if (sysent[tcp->scno].sys_func == sys_write ||
1884 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001885 sysent[tcp->scno].sys_func == sys_send ||
1886 sysent[tcp->scno].sys_func == sys_sendto)
1887 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1888 else if (sysent[tcp->scno].sys_func == sys_writev)
1889 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1890 return;
1891 }
1892}
1893
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001894static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001895trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001896{
1897 int sys_res;
1898 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001899 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001900 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001901
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001902 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001903 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001904 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001905
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001906#if SUPPORTED_PERSONALITIES > 1
1907 update_personality(tcp, tcp->currpers);
1908#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001909 res = get_syscall_result(tcp);
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001910 if (res == 1) {
1911 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01001912 res = get_error(tcp); /* returns 1 or -1 */
1913 if (res == 1) {
1914 internal_syscall(tcp);
1915 if (filtered(tcp)) {
1916 goto ret;
1917 }
1918 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00001919 }
1920
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001921 if (cflag) {
1922 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02001923 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02001924 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001925 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001926 }
1927 }
1928
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01001929 /* If not in -ff mode, and printing_tcp != tcp,
1930 * then the log currently does not end with output
1931 * of _our syscall entry_, but with something else.
1932 * We need to say which syscall's return is this.
1933 *
1934 * Forced reprinting via TCB_REPRINT is used only by
1935 * "strace -ff -oLOG test/threaded_execve" corner case.
1936 * It's the only case when -ff mode needs reprinting.
1937 */
1938 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
1939 tcp->flags &= ~TCB_REPRINT;
1940 printleader(tcp);
1941 if (!SCNO_IN_RANGE(tcp->scno))
1942 tprintf("<... syscall_%lu resumed> ", tcp->scno);
1943 else
1944 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
1945 }
1946 printing_tcp = tcp;
1947
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001948 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01001949 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001950 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001951 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01001952 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001953 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001954 tcp->flags &= ~TCB_INSYSCALL;
1955 return res;
1956 }
1957
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01001958 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001959 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001960 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01001961 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001962 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001963 /* FIXME: not_failing_only (IOW, option -z) is broken:
1964 * failure of syscall is known only after syscall return.
1965 * Thus we end up with something like this on, say, ENOENT:
1966 * open("doesnt_exist", O_RDONLY <unfinished ...>
1967 * {next syscall decode}
1968 * whereas the intended result is that open(...) line
1969 * is not shown at all.
1970 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001971 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02001972 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001973 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
1974 }
1975
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001976 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001977 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02001978 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001979 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001980 qual_flags[tcp->scno] & QUAL_RAW) {
1981 if (u_error)
1982 tprintf("= -1 (errno %ld)", u_error);
1983 else
1984 tprintf("= %#lx", tcp->u_rval);
1985 }
1986 else if (!(sys_res & RVAL_NONE) && u_error) {
1987 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01001988 /* Blocked signals do not interrupt any syscalls.
1989 * In this case syscalls don't return ERESTARTfoo codes.
1990 *
1991 * Deadly signals set to SIG_DFL interrupt syscalls
1992 * and kill the process regardless of which of the codes below
1993 * is returned by the interrupted syscall.
1994 * In some cases, kernel forces a kernel-generated deadly
1995 * signal to be unblocked and set to SIG_DFL (and thus cause
1996 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
1997 * or SIGILL. (The alternative is to leave process spinning
1998 * forever on the faulty instruction - not useful).
1999 *
2000 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2001 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2002 * but kernel will always restart them.
2003 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002004 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002005 /* Most common type of signal-interrupted syscall exit code.
2006 * The system call will be restarted with the same arguments
2007 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2008 */
2009 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002010 break;
2011 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002012 /* Rare. For example, fork() returns this if interrupted.
2013 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2014 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002015 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002016 break;
2017 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002018 /* pause(), rt_sigsuspend() etc use this code.
2019 * SA_RESTART is ignored (assumed not set):
2020 * syscall won't restart (will return EINTR instead)
2021 * even after signal with SA_RESTART set.
2022 * However, after SIG_IGN or SIG_DFL signal it will.
2023 */
2024 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002025 break;
2026 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002027 /* Syscalls like nanosleep(), poll() which can't be
2028 * restarted with their original arguments use this
2029 * code. Kernel will execute restart_syscall() instead,
2030 * which changes arguments before restarting syscall.
2031 * SA_RESTART is ignored (assumed not set) similarly
2032 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2033 * since restart data is saved in "restart block"
2034 * in task struct, and if signal handler uses a syscall
2035 * which in turn saves another such restart block,
2036 * old data is lost and restart becomes impossible)
2037 */
2038 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002039 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002040 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002041 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002042 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002043 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002044 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002045 strerror(u_error));
2046 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002047 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002048 strerror(u_error));
2049 break;
2050 }
2051 if ((sys_res & RVAL_STR) && tcp->auxstr)
2052 tprintf(" (%s)", tcp->auxstr);
2053 }
2054 else {
2055 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002056 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002057 else {
2058 switch (sys_res & RVAL_MASK) {
2059 case RVAL_HEX:
2060 tprintf("= %#lx", tcp->u_rval);
2061 break;
2062 case RVAL_OCTAL:
2063 tprintf("= %#lo", tcp->u_rval);
2064 break;
2065 case RVAL_UDECIMAL:
2066 tprintf("= %lu", tcp->u_rval);
2067 break;
2068 case RVAL_DECIMAL:
2069 tprintf("= %ld", tcp->u_rval);
2070 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002071#if defined(LINUX_MIPSN32) || defined(X32)
2072 /*
2073 case RVAL_LHEX:
2074 tprintf("= %#llx", tcp->u_lrval);
2075 break;
2076 case RVAL_LOCTAL:
2077 tprintf("= %#llo", tcp->u_lrval);
2078 break;
2079 */
2080 case RVAL_LUDECIMAL:
2081 tprintf("= %llu", tcp->u_lrval);
2082 break;
2083 /*
2084 case RVAL_LDECIMAL:
2085 tprintf("= %lld", tcp->u_lrval);
2086 break;
2087 */
2088#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002089 default:
2090 fprintf(stderr,
2091 "invalid rval format\n");
2092 break;
2093 }
2094 }
2095 if ((sys_res & RVAL_STR) && tcp->auxstr)
2096 tprintf(" (%s)", tcp->auxstr);
2097 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002098 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002099 tv_sub(&tv, &tv, &tcp->etime);
2100 tprintf(" <%ld.%06ld>",
2101 (long) tv.tv_sec, (long) tv.tv_usec);
2102 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002103 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002104 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002105 line_ended();
2106
Denys Vlasenko3b738812011-08-22 02:06:35 +02002107 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002108 tcp->flags &= ~TCB_INSYSCALL;
2109 return 0;
2110}
2111
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002112int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002113trace_syscall(struct tcb *tcp)
2114{
2115 return exiting(tcp) ?
2116 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2117}