blob: 8d74f6840ac8eab038ecaa5c78e404a2a9ab1fc0 [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 Vlasenko5ae2b7c2009-02-27 20:32:52 +0000340 if (isdigit((unsigned char)*s)) {
341 int i = atoi(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++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000348 if (strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000349 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000350 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000351 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000352
353#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000354 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000355 if (strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000356 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000357 rc = 0;
358 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100359#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000360
361#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000362 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000363 if (strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000364 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000365 rc = 0;
366 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100367#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000368
Roland McGrathfe6b3522005-02-02 04:40:11 +0000369 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000370}
371
372static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000373qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000374{
375 int i;
376 char buf[32];
377
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000378 if (isdigit((unsigned char)*s)) {
379 int signo = atoi(s);
380 if (signo < 0 || signo >= MAX_QUALS)
381 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000382 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000383 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000384 }
Roland McGrathd62b6712004-03-02 06:52:01 +0000385 if (strlen(s) >= sizeof buf)
Roland McGrathfe6b3522005-02-02 04:40:11 +0000386 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000387 strcpy(buf, s);
388 s = buf;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000389 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000390 s += 3;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000391 for (i = 0; i <= NSIG; i++)
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000392 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000393 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000394 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000395 }
Roland McGrath76421df2005-02-02 03:51:18 +0000396 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000397}
398
399static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000400qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000401{
402 return -1;
403}
404
405static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000406qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000407{
Roland McGrath48a035f2006-01-12 09:45:56 +0000408 if (isdigit((unsigned char)*s)) {
Roland McGrathfe6b3522005-02-02 04:40:11 +0000409 int desc = atoi(s);
410 if (desc < 0 || desc >= MAX_QUALS)
411 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000412 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000413 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000414 }
415 return -1;
416}
417
418static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000419lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000420{
421 if (strcmp(s, "file") == 0)
422 return TRACE_FILE;
423 if (strcmp(s, "ipc") == 0)
424 return TRACE_IPC;
425 if (strcmp(s, "network") == 0)
426 return TRACE_NETWORK;
427 if (strcmp(s, "process") == 0)
428 return TRACE_PROCESS;
429 if (strcmp(s, "signal") == 0)
430 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000431 if (strcmp(s, "desc") == 0)
432 return TRACE_DESC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000433 return -1;
434}
435
436void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000437qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000438{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000439 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000440 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000441 char *copy;
442 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000443 int i, n;
444
445 opt = &qual_options[0];
446 for (i = 0; (p = qual_options[i].option_name); i++) {
447 n = strlen(p);
448 if (strncmp(s, p, n) == 0 && s[n] == '=') {
449 opt = &qual_options[i];
450 s += n + 1;
451 break;
452 }
453 }
454 not = 0;
455 if (*s == '!') {
456 not = 1;
457 s++;
458 }
459 if (strcmp(s, "none") == 0) {
460 not = 1 - not;
461 s = "all";
462 }
463 if (strcmp(s, "all") == 0) {
464 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000465 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000466 }
467 return;
468 }
469 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000470 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000471 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200472 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200473 if (!copy)
474 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000475 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000476 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000477 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000478 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000479 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000480
481#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000482 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000483 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000484 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100485#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000486
487#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000488 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000489 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000490 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100491#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000492
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000493 continue;
494 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000495 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100496 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000497 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000498 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000499 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000500 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000501 return;
502}
503
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000504#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000505static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000506decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000507{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000508 unsigned long addr;
509 unsigned int i, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000510
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000511 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
512 return;
513
514 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
515 addr = tcp->u_arg[1];
516 tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100517 size = current_wordsize;
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000518 for (i = 0; i < tcp->u_nargs; ++i) {
519 if (size == sizeof(int)) {
520 unsigned int arg;
521 if (umove(tcp, addr, &arg) < 0)
522 arg = 0;
523 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000524 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000525 else {
526 unsigned long arg;
527 if (umove(tcp, addr, &arg) < 0)
528 arg = 0;
529 tcp->u_arg[i] = arg;
530 }
531 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000532 }
533}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000534#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400535
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000536#ifdef SYS_ipc_subcall
537static void
538decode_ipc_subcall(struct tcb *tcp)
539{
540 unsigned int i;
541
542 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
543 return;
544
545 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
546 tcp->u_nargs = sysent[tcp->scno].nargs;
547 for (i = 0; i < tcp->u_nargs; i++)
548 tcp->u_arg[i] = tcp->u_arg[i + 1];
549}
550#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000551
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200552int
553printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000554{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200555 if (entering(tcp)) {
556 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000557
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200558 for (i = 0; i < tcp->u_nargs; i++)
559 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
560 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000561 return 0;
562}
563
Denys Vlasenko72879c62012-02-27 14:18:02 +0100564int
565printargs_lu(struct tcb *tcp)
566{
567 if (entering(tcp)) {
568 int i;
569
570 for (i = 0; i < tcp->u_nargs; i++)
571 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
572 }
573 return 0;
574}
575
576int
577printargs_ld(struct tcb *tcp)
578{
579 if (entering(tcp)) {
580 int i;
581
582 for (i = 0; i < tcp->u_nargs; i++)
583 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
584 }
585 return 0;
586}
587
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200588long
589getrval2(struct tcb *tcp)
590{
591 long val = -1;
592
Denys Vlasenko523635f2012-02-25 02:44:25 +0100593#if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200594 struct pt_regs regs;
595 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
596 return -1;
597 val = regs.u_regs[U_REG_O1];
598#elif defined(SH)
599 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
600 return -1;
601#elif defined(IA64)
602 if (upeek(tcp, PT_R9, &val) < 0)
603 return -1;
604#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200605
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200606 return val;
607}
608
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200609int
610is_restart_error(struct tcb *tcp)
611{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200612 switch (tcp->u_error) {
613 case ERESTARTSYS:
614 case ERESTARTNOINTR:
615 case ERESTARTNOHAND:
616 case ERESTART_RESTARTBLOCK:
617 return 1;
618 default:
619 break;
620 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200621 return 0;
622}
623
Denys Vlasenko523635f2012-02-25 02:44:25 +0100624#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100625struct pt_regs i386_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100626#elif defined(X86_64)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100627/*
628 * On 32 bits, pt_regs and user_regs_struct are the same,
629 * but on 64 bits, user_regs_struct has six more fields:
630 * fs_base, gs_base, ds, es, fs, gs.
631 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
632 */
633static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100634#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200635long r8, r10, psr; /* TODO: make static? */
636long ia32 = 0; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100637#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +0200638static long result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100639#elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200640static long d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100641#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200642static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100643#elif defined(ARM)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200644static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100645#elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200646static long r0;
647static long a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100648#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200649static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100650#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200651static struct pt_regs regs;
652static unsigned long trap;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100653#elif defined(LINUX_MIPSN32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200654static long long a3;
655static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100656#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200657static long a3;
658static long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100659#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200660static long gpr2;
661static long pc;
662static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100663#elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200664static long r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100665#elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200666static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100667#elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200668static long r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100669#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200670static long r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100671#elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200672static long r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100673#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000674
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200675/* Returns:
676 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
677 * 1: ok, continue in trace_syscall().
678 * other: error, trace_syscall() should print error indicator
679 * ("????" etc) and bail out.
680 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100681static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200682get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000683{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000684 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000685
Denys Vlasenko523635f2012-02-25 02:44:25 +0100686#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000687 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200688 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000689
690 if (syscall_mode != -ENOSYS) {
691 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000692 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000693 */
694 scno = syscall_mode;
695 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000696 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000697 * Old style of "passing" the scno via the SVC instruction.
698 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000699 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200700 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200701 static const int gpr_offset[16] = {
702 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
703 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
704 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
705 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
706 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000707
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000708 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000709 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000710 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000711 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000712 if (errno) {
713 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000714 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000715 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000716
717 /*
718 * We have to check if the SVC got executed directly or via an
719 * EXECUTE instruction. In case of EXECUTE it is necessary to do
720 * instruction decoding to derive the system call number.
721 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
722 * so that this doesn't work if a SVC opcode is part of an EXECUTE
723 * opcode. Since there is no way to find out the opcode size this
724 * is the best we can do...
725 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000726 if ((opcode & 0xff00) == 0x0a00) {
727 /* SVC opcode */
728 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000729 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000730 else {
731 /* SVC got executed by EXECUTE instruction */
732
733 /*
734 * Do instruction decoding of EXECUTE. If you really want to
735 * understand this, read the Principles of Operations.
736 */
737 svc_addr = (void *) (opcode & 0xfff);
738
739 tmp = 0;
740 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000741 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000742 return -1;
743 svc_addr += tmp;
744
745 tmp = 0;
746 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000747 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000748 return -1;
749 svc_addr += tmp;
750
Denys Vlasenkofb036672009-01-23 16:30:26 +0000751 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000752 if (errno)
753 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100754# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000755 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100756# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000757 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100758# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000759 tmp = 0;
760 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000761 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000762 return -1;
763
764 scno = (scno | tmp) & 0xff;
765 }
766 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100767#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000768 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000769 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100770# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200771 /* TODO: speed up strace by not doing this at every syscall.
772 * We only need to do it after execve.
773 */
774 int currpers;
775 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200776
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200777 /* Check for 64/32 bit mode. */
778 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
779 return -1;
780 /* SF is bit 0 of MSR */
781 if (val < 0)
782 currpers = 0;
783 else
784 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000785 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100786# endif
787#elif defined(AVR32)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200788 /* Read complete register set in one go. */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000789 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
790 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200791 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100792#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000793 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000794 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100795#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200796 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000797 return -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200798 scno = i386_regs.orig_eax;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100799#elif defined(X86_64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200800 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200801 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
802 return -1;
803 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +0000804
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200805 /* Check CS register value. On x86-64 linux it is:
806 * 0x33 for long mode (64 bit)
807 * 0x23 for compatibility mode (32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200808 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200809 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200810 case 0x23: currpers = 1; break;
811 case 0x33: currpers = 0; break;
812 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200813 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200814 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200815 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200816 currpers = current_personality;
817 break;
818 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100819# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200820 /* This version analyzes the opcode of a syscall instruction.
821 * (int 0x80 on i386 vs. syscall on x86-64)
822 * It works, but is too complicated.
823 */
824 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +0000825
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200826 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +0000827
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200828 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
829 rip -= 2;
830 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +0000831
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200832 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200833 if (errno)
834 fprintf(stderr, "ptrace_peektext failed: %s\n",
835 strerror(errno));
836 switch (call & 0xffff) {
837 /* x86-64: syscall = 0x0f 0x05 */
838 case 0x050f: currpers = 0; break;
839 /* i386: int 0x80 = 0xcd 0x80 */
840 case 0x80cd: currpers = 1; break;
841 default:
842 currpers = current_personality;
843 fprintf(stderr,
844 "Unknown syscall opcode (0x%04X) while "
845 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200846 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200847 break;
848 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100849# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000850 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100851#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000852# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200853 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000854 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200855 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200856 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200857 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000858 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200859 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000860 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200861 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100862#elif defined(ARM)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200863 /* Read complete register set in one go. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000864 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +0000865 return -1;
866
867 /*
868 * We only need to grab the syscall number on syscall entry.
869 */
870 if (regs.ARM_ip == 0) {
871 /*
872 * Note: we only deal with only 32-bit CPUs here.
873 */
874 if (regs.ARM_cpsr & 0x20) {
875 /*
876 * Get the Thumb-mode system call number
877 */
878 scno = regs.ARM_r7;
879 } else {
880 /*
881 * Get the ARM-mode system call number
882 */
883 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000884 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +0000885 if (errno)
886 return -1;
887
Roland McGrathf691bd22006-04-25 07:34:41 +0000888 /* Handle the EABI syscall convention. We do not
889 bother converting structures between the two
890 ABIs, but basic functionality should work even
891 if strace and the traced program have different
892 ABIs. */
893 if (scno == 0xef000000) {
894 scno = regs.ARM_r7;
895 } else {
896 if ((scno & 0x0ff00000) != 0x0f900000) {
897 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
898 scno);
899 return -1;
900 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000901
Roland McGrathf691bd22006-04-25 07:34:41 +0000902 /*
903 * Fixup the syscall number
904 */
905 scno &= 0x000fffff;
906 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000907 }
Roland McGrath56703312008-05-20 01:35:55 +0000908 if (scno & 0x0f0000) {
909 /*
910 * Handle ARM specific syscall
911 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000912 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +0000913 scno &= 0x0000ffff;
914 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000915 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +0000916
Roland McGrath0f87c492003-06-03 23:29:04 +0000917 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200918 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
919 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000920 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100921#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000922 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000923 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100924#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +0000925 unsigned long long regs[38];
926
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200927 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +0000928 return -1;
929 a3 = regs[REG_A3];
930 r2 = regs[REG_V0];
931
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200932 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200933 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200934 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100935 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200936 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000937 return 0;
938 }
Roland McGrath542c2c62008-05-20 01:11:56 +0000939 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100940#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000941 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000942 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200943 if (upeek(tcp, REG_V0, &scno) < 0)
944 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000945
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200946 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200947 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100948 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200949 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000950 return 0;
951 }
Wichert Akkermanf90da011999-10-31 21:15:38 +0000952 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100953#elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000954 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000955 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200956 if (upeek(tcp, REG_R0, &scno) < 0)
957 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200959 /*
960 * Do some sanity checks to figure out if it's
961 * really a syscall entry
962 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200963 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200964 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100965 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200966 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000967 return 0;
968 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000969 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100970#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000972 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000973 return -1;
974
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200975 /* Disassemble the syscall trap. */
976 /* Retrieve the syscall trap instruction. */
977 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100978# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200979 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
980 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100981# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200982 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100983# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200984 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +0000985 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200986
987 /* Disassemble the trap to see what personality to use. */
988 switch (trap) {
989 case 0x91d02010:
990 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000991 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200992 break;
993 case 0x91d0206d:
994 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000995 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200996 break;
997 case 0x91d02000:
998 /* SunOS syscall trap. (pers 1) */
999 fprintf(stderr, "syscall: SunOS no support\n");
1000 return -1;
1001 case 0x91d02008:
1002 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001003 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001004 break;
1005 case 0x91d02009:
1006 /* NetBSD/FreeBSD syscall trap. */
1007 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1008 return -1;
1009 case 0x91d02027:
1010 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001011 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001012 break;
1013 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001014# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001015 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001016# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001017 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001018# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001019 return -1;
1020 }
1021
1022 /* Extract the system call number from the registers. */
1023 if (trap == 0x91d02027)
1024 scno = 156;
1025 else
1026 scno = regs.u_regs[U_REG_G1];
1027 if (scno == 0) {
1028 scno = regs.u_regs[U_REG_O0];
1029 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1030 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001031#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001032 if (upeek(tcp, PT_GR20, &scno) < 0)
1033 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001034#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001035 /*
1036 * In the new syscall ABI, the system call number is in R3.
1037 */
1038 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1039 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001040
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001041 if (scno < 0) {
1042 /* Odd as it may seem, a glibc bug has been known to cause
1043 glibc to issue bogus negative syscall numbers. So for
1044 our purposes, make strace print what it *should* have been */
1045 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001046 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001047 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001048 "Detected glibc bug: bogus system call"
1049 " number = %ld, correcting to %ld\n",
1050 scno,
1051 correct_scno);
1052 scno = correct_scno;
1053 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001054#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001055 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001056 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001057 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001058#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001059 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1060 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001061#elif defined(TILE)
Chris Metcalfc8c66982009-12-28 10:00:15 -05001062 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1063 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001064#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001065 if (upeek(tcp, 0, &scno) < 0)
1066 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001067#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001068
Denys Vlasenko523635f2012-02-25 02:44:25 +01001069#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001070 /* new syscall ABI returns result in R0 */
1071 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1072 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001073#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001074 /* ABI defines result returned in r9 */
1075 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1076 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001077#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001078
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001079 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001080 return 1;
1081}
1082
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001083/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001084 * Returns:
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001085 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
Roland McGratheb9e2e82009-06-02 16:49:22 -07001086 * 1: ok, continue in trace_syscall().
1087 * other: error, trace_syscall() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001088 * ("????" etc) and bail out.
1089 */
Roland McGratha4d48532005-06-08 20:45:28 +00001090static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001091syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001092{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001093 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001094#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001095 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001096 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001097 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1098 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001099 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001100#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001101 {
1102 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001103 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001104 rax = (int)rax; /* sign extend from 32 bits */
1105 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001106 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001107 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1108 return 0;
1109 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001110 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001111#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001112 /* TODO: we already fetched PT_GPR2 in get_scno
1113 * and stored it in syscall_mode, reuse it here
1114 * instead of re-fetching?
1115 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001116 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001117 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001118 if (syscall_mode != -ENOSYS)
1119 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001120 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001121 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001122 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001123 return 0;
1124 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001125#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001126 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001127 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001128 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001129 if (d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001130 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001131 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001132 return 0;
1133 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001134#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001135 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001136 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001137 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001138 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001139 if (ia32 && r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001140 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001141 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001142 return 0;
1143 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001144#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001145 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001146 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001147 if (r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001148 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001149 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001150 return 0;
1151 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001152#elif defined(MICROBLAZE)
1153 if (upeek(tcp, 3 * 4, &r3) < 0)
1154 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001155 if (r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001156 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001157 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001158 return 0;
1159 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001160#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001161 return 1;
1162}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163
Denys Vlasenko146b9442012-03-18 22:10:48 +01001164static void
1165internal_fork(struct tcb *tcp)
1166{
1167#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1168# define ARG_FLAGS 1
1169#else
1170# define ARG_FLAGS 0
1171#endif
1172#ifndef CLONE_UNTRACED
1173# define CLONE_UNTRACED 0x00800000
1174#endif
1175 if ((ptrace_setoptions
1176 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1177 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1178 return;
1179
1180 if (!followfork)
1181 return;
1182
1183 if (entering(tcp)) {
1184 /*
1185 * We won't see the new child if clone is called with
1186 * CLONE_UNTRACED, so we keep the same logic with that option
1187 * and don't trace it.
1188 */
1189 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1190 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1191 return;
1192 setbpt(tcp);
1193 } else {
1194 if (tcp->flags & TCB_BPTSET)
1195 clearbpt(tcp);
1196 }
1197}
1198
1199#if defined(TCB_WAITEXECVE)
1200static void
1201internal_exec(struct tcb *tcp)
1202{
1203 /* Maybe we have post-execve SIGTRAP suppressed? */
1204 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1205 return; /* yes, no need to do anything */
1206
1207 if (exiting(tcp) && syserror(tcp))
1208 /* Error in execve, no post-execve SIGTRAP expected */
1209 tcp->flags &= ~TCB_WAITEXECVE;
1210 else
1211 tcp->flags |= TCB_WAITEXECVE;
1212}
1213#endif
1214
1215static void
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001216internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001217{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001218 /*
1219 * We must always trace a few critical system calls in order to
1220 * correctly support following forks in the presence of tracing
1221 * qualifiers.
1222 */
1223 int (*func)();
1224
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001225 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001226 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001227
1228 func = sysent[tcp->scno].sys_func;
1229
1230 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001231 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001232 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001233 ) {
1234 internal_fork(tcp);
1235 return;
1236 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001237
Denys Vlasenko84703742012-02-25 02:38:52 +01001238#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001239 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001240# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001241 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001242# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001243 ) {
1244 internal_exec(tcp);
1245 return;
1246 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001247#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001248}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001249
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001250/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001251static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001252get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001253{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001254 int i, nargs;
1255
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001256 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001257 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001258 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001259 nargs = tcp->u_nargs = MAX_ARGS;
1260
Denys Vlasenko523635f2012-02-25 02:44:25 +01001261#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001262 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001263 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1264 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001265#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001266 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001267 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1268 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001269#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001270 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001271 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001272 long rbs_end;
1273 /* be backwards compatible with kernel < 2.4.4... */
1274# ifndef PT_RBS_END
1275# define PT_RBS_END PT_AR_BSP
1276# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001277
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001278 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1279 return -1;
1280 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001281 return -1;
1282
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001283 sof = (cfm >> 0) & 0x7f;
1284 sol = (cfm >> 7) & 0x7f;
1285 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1286
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001287 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001288 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1289 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1290 return -1;
1291 }
1292 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001293 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1294 PT_R9 /* ECX = out1 */,
1295 PT_R10 /* EDX = out2 */,
1296 PT_R14 /* ESI = out3 */,
1297 PT_R15 /* EDI = out4 */,
1298 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001299
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001300 for (i = 0; i < nargs; ++i) {
1301 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1302 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001303 /* truncate away IVE sign-extension */
1304 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001305 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001306 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001307#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001308 /* N32 and N64 both use up to six registers. */
1309 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001310
1311 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1312 return -1;
1313
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001314 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001315 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001316# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001317 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001318# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001319 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001320#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001321 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001322 long sp;
1323
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001324 if (upeek(tcp, REG_SP, &sp) < 0)
1325 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001326 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001327 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1328 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001329 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001330 (char *)(tcp->u_arg + 4));
1331 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001332 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001333 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001334 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001335 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001336#elif defined(POWERPC)
1337# ifndef PT_ORIG_R3
1338# define PT_ORIG_R3 34
1339# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001340 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001341 if (upeek(tcp, (i==0) ?
1342 (sizeof(unsigned long) * PT_ORIG_R3) :
1343 ((i+PT_R3) * sizeof(unsigned long)),
1344 &tcp->u_arg[i]) < 0)
1345 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001346 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001347#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001348 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001349 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001350#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001351 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001352 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1353 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001354#elif defined(ARM)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001355 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001356 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001357#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001358 (void)i;
1359 (void)nargs;
1360 tcp->u_arg[0] = regs.r12;
1361 tcp->u_arg[1] = regs.r11;
1362 tcp->u_arg[2] = regs.r10;
1363 tcp->u_arg[3] = regs.r9;
1364 tcp->u_arg[4] = regs.r5;
1365 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001366#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001367 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 +02001368
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001369 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001370 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1371 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001372#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001373 static const int syscall_regs[MAX_ARGS] = {
1374 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1375 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001376 };
1377
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001378 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001379 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001380 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001381#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001382 int i;
1383 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001384 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001385
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001386 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001387 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1388 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001389#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001390 (void)i;
1391 (void)nargs;
1392 if (current_personality == 0) { /* x86-64 ABI */
1393 tcp->u_arg[0] = x86_64_regs.rdi;
1394 tcp->u_arg[1] = x86_64_regs.rsi;
1395 tcp->u_arg[2] = x86_64_regs.rdx;
1396 tcp->u_arg[3] = x86_64_regs.r10;
1397 tcp->u_arg[4] = x86_64_regs.r8;
1398 tcp->u_arg[5] = x86_64_regs.r9;
1399 } else { /* i386 ABI */
1400 /* Sign-extend lower 32 bits */
1401 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1402 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1403 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1404 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1405 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1406 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1407 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001408#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001409 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001410 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1411 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001412#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001413 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001414 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001415 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001416 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001417
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001418 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001419 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1420 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001421#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001422 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001423 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1424 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001425#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001426 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001427 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1428 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001429#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001430 (void)i;
1431 (void)nargs;
1432 tcp->u_arg[0] = i386_regs.ebx;
1433 tcp->u_arg[1] = i386_regs.ecx;
1434 tcp->u_arg[2] = i386_regs.edx;
1435 tcp->u_arg[3] = i386_regs.esi;
1436 tcp->u_arg[4] = i386_regs.edi;
1437 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001438#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001439 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001440 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1441 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001442#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001443 return 1;
1444}
1445
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001446static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001447trace_syscall_entering(struct tcb *tcp)
1448{
1449 int res, scno_good;
1450
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001451#if defined TCB_WAITEXECVE
1452 if (tcp->flags & TCB_WAITEXECVE) {
1453 /* This is the post-execve SIGTRAP. */
1454 tcp->flags &= ~TCB_WAITEXECVE;
1455 return 0;
1456 }
1457#endif
1458
Denys Vlasenko06602d92011-08-24 17:53:52 +02001459 scno_good = res = get_scno(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001460 if (res == 0)
1461 return res;
1462 if (res == 1)
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001463 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001464 if (res == 0)
1465 return res;
1466 if (res == 1)
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001467 res = get_syscall_args(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001468
1469 if (res != 1) {
1470 printleader(tcp);
1471 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001472 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001473 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001474 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001475 tprintf("syscall_%lu(", tcp->scno);
1476 else
1477 tprintf("%s(", sysent[tcp->scno].sys_name);
1478 /*
1479 * " <unavailable>" will be added later by the code which
1480 * detects ptrace errors.
1481 */
1482 goto ret;
1483 }
1484
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001485#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1486 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001487# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001488 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001489 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001490 break;
1491 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001492# endif
1493# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001494 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001495 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001496 break;
1497 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001498# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001499 break;
1500 }
1501#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1502
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001503 internal_syscall(tcp);
1504
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001505 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001506 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1507 (tracing_paths && !pathtrace_match(tcp))) {
1508 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1509 return 0;
1510 }
1511
1512 tcp->flags &= ~TCB_FILTERED;
1513
1514 if (cflag == CFLAG_ONLY_STATS) {
1515 res = 0;
1516 goto ret;
1517 }
1518
1519 printleader(tcp);
1520 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001521 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001522 tprintf("syscall_%lu(", tcp->scno);
1523 else
1524 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001525 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001526 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1527 sysent[tcp->scno].sys_func != sys_exit))
1528 res = printargs(tcp);
1529 else
1530 res = (*sysent[tcp->scno].sys_func)(tcp);
1531
1532 if (fflush(tcp->outf) == EOF)
1533 return -1;
1534 ret:
1535 tcp->flags |= TCB_INSYSCALL;
1536 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001537 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001538 gettimeofday(&tcp->etime, NULL);
1539 return res;
1540}
1541
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001542/* Returns:
1543 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1544 * 1: ok, continue in trace_syscall().
1545 * other: error, trace_syscall() should print error indicator
1546 * ("????" etc) and bail out.
1547 */
1548static int
1549get_syscall_result(struct tcb *tcp)
1550{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001551#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001552 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1553 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001554#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001555# define SO_MASK 0x10000000
1556 {
1557 long flags;
1558 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1559 return -1;
1560 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &result) < 0)
1561 return -1;
1562 if (flags & SO_MASK)
1563 result = -result;
1564 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001565#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001566 /* Read complete register set in one go. */
1567 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1568 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001569#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001570 if (upeek(tcp, PT_R0, &r0) < 0)
1571 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001572#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001573 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001574 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001575#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001576 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001577 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001578#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001579# define IA64_PSR_IS ((long)1 << 34)
1580 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1581 ia32 = (psr & IA64_PSR_IS) != 0;
1582 if (upeek(tcp, PT_R8, &r8) < 0)
1583 return -1;
1584 if (upeek(tcp, PT_R10, &r10) < 0)
1585 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001586#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001587 /* Read complete register set in one go. */
1588 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1589 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001590#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001591 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1592 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001593#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001594 unsigned long long regs[38];
1595
1596 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1597 return -1;
1598 a3 = regs[REG_A3];
1599 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001600#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001601 if (upeek(tcp, REG_A3, &a3) < 0)
1602 return -1;
1603 if (upeek(tcp, REG_V0, &r2) < 0)
1604 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001605#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001606 if (upeek(tcp, REG_A3, &a3) < 0)
1607 return -1;
1608 if (upeek(tcp, REG_R0, &r0) < 0)
1609 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001610#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001611 /* Everything we need is in the current register set. */
1612 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1613 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001614#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001615 if (upeek(tcp, PT_GR28, &r28) < 0)
1616 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001617#elif defined(SH)
1618#elif defined(SH64)
1619#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001620 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1621 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001622#elif defined(TILE)
1623#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001624 if (upeek(tcp, 3 * 4, &r3) < 0)
1625 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001626#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001627
Denys Vlasenko523635f2012-02-25 02:44:25 +01001628#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001629 /* new syscall ABI returns result in R0 */
1630 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1631 return -1;
1632#elif defined(SH64)
1633 /* ABI defines result returned in r9 */
1634 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1635 return -1;
1636#endif
1637
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001638 return 1;
1639}
1640
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001641/* Called at each syscall exit */
1642static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001643syscall_fixup_on_sysexit(struct tcb *tcp)
1644{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001645#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001646 if (syscall_mode != -ENOSYS)
1647 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001648 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001649 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1650 /*
1651 * Return from execve.
1652 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1653 * flag set for the post-execve SIGTRAP to see and reset.
1654 */
1655 gpr2 = 0;
1656 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001657#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001658}
1659
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001660/*
1661 * Check the syscall return value register value for whether it is
1662 * a negated errno code indicating an error, or a success return value.
1663 */
1664static inline int
1665is_negated_errno(unsigned long int val)
1666{
1667 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001668#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001669 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001670 val = (unsigned int) val;
1671 max = (unsigned int) max;
1672 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001673#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001674 return val > max;
1675}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001676
1677static int
1678get_error(struct tcb *tcp)
1679{
1680 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001681 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001682 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001683 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1684 check_errno = 0;
1685 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001686#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001687 if (check_errno && is_negated_errno(gpr2)) {
1688 tcp->u_rval = -1;
1689 u_error = -gpr2;
1690 }
1691 else {
1692 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001693 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001694#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001695 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001696 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001697 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001698 }
1699 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001700 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001701 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001702#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001703 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001704 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001705 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001706 }
1707 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001708 tcp->u_rval = x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001709 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001710#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001711 if (ia32) {
1712 int err;
1713
1714 err = (int)r8;
1715 if (check_errno && is_negated_errno(err)) {
1716 tcp->u_rval = -1;
1717 u_error = -err;
1718 }
1719 else {
1720 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001721 }
1722 } else {
1723 if (check_errno && r10) {
1724 tcp->u_rval = -1;
1725 u_error = r8;
1726 } else {
1727 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001728 }
1729 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001730#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001731 if (check_errno && a3) {
1732 tcp->u_rval = -1;
1733 u_error = r2;
1734 } else {
1735 tcp->u_rval = r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001736 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001737#elif defined(POWERPC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001738 if (check_errno && is_negated_errno(result)) {
1739 tcp->u_rval = -1;
1740 u_error = -result;
1741 }
1742 else {
1743 tcp->u_rval = result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001744 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001745#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001746 if (check_errno && is_negated_errno(d0)) {
1747 tcp->u_rval = -1;
1748 u_error = -d0;
1749 }
1750 else {
1751 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001752 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001753#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001754 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1755 tcp->u_rval = -1;
1756 u_error = -regs.ARM_r0;
1757 }
1758 else {
1759 tcp->u_rval = regs.ARM_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001760 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001761#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001762 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1763 tcp->u_rval = -1;
1764 u_error = -regs.r12;
1765 }
1766 else {
1767 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001768 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001769#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001770 if (check_errno && is_negated_errno(r0)) {
1771 tcp->u_rval = -1;
1772 u_error = -r0;
1773 } else {
1774 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001775 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001776#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001777 if (check_errno && a3) {
1778 tcp->u_rval = -1;
1779 u_error = r0;
1780 }
1781 else {
1782 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001783 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001784#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001785 if (check_errno && regs.psr & PSR_C) {
1786 tcp->u_rval = -1;
1787 u_error = regs.u_regs[U_REG_O0];
1788 }
1789 else {
1790 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001791 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001792#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001793 if (check_errno && regs.tstate & 0x1100000000UL) {
1794 tcp->u_rval = -1;
1795 u_error = regs.u_regs[U_REG_O0];
1796 }
1797 else {
1798 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001799 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001800#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001801 if (check_errno && is_negated_errno(r28)) {
1802 tcp->u_rval = -1;
1803 u_error = -r28;
1804 }
1805 else {
1806 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001807 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001808#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001809 if (check_errno && is_negated_errno(r0)) {
1810 tcp->u_rval = -1;
1811 u_error = -r0;
1812 }
1813 else {
1814 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001815 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001816#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001817 if (check_errno && is_negated_errno(r9)) {
1818 tcp->u_rval = -1;
1819 u_error = -r9;
1820 }
1821 else {
1822 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001823 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001824#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001825 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1826 tcp->u_rval = -1;
1827 u_error = -r10;
1828 }
1829 else {
1830 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001831 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001832#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001833 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001834 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1835 return -1;
1836 if (check_errno && rval < 0 && rval > -nerrnos) {
1837 tcp->u_rval = -1;
1838 u_error = -rval;
1839 }
1840 else {
1841 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001842 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001843#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001844 if (check_errno && is_negated_errno(r3)) {
1845 tcp->u_rval = -1;
1846 u_error = -r3;
1847 }
1848 else {
1849 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001850 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001851#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001852 tcp->u_error = u_error;
1853 return 1;
1854}
1855
1856static void
1857dumpio(struct tcb *tcp)
1858{
1859 if (syserror(tcp))
1860 return;
1861 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1862 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001863 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001864 return;
1865 if (sysent[tcp->scno].sys_func == printargs)
1866 return;
1867 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1868 if (sysent[tcp->scno].sys_func == sys_read ||
1869 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001870 sysent[tcp->scno].sys_func == sys_recv ||
1871 sysent[tcp->scno].sys_func == sys_recvfrom)
1872 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1873 else if (sysent[tcp->scno].sys_func == sys_readv)
1874 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1875 return;
1876 }
1877 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1878 if (sysent[tcp->scno].sys_func == sys_write ||
1879 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001880 sysent[tcp->scno].sys_func == sys_send ||
1881 sysent[tcp->scno].sys_func == sys_sendto)
1882 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1883 else if (sysent[tcp->scno].sys_func == sys_writev)
1884 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1885 return;
1886 }
1887}
1888
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001889static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001890trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001891{
1892 int sys_res;
1893 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001894 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001895 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001896
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001897 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001898 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001899 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001900
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001901#if SUPPORTED_PERSONALITIES > 1
1902 update_personality(tcp, tcp->currpers);
1903#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001904 res = get_syscall_result(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001905 if (res == 0)
1906 return res;
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001907 if (res == 1) {
1908 syscall_fixup_on_sysexit(tcp); /* never fails */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001909 res = get_error(tcp);
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001910 }
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001911 if (res == 0)
1912 return res;
1913 if (res == 1)
1914 internal_syscall(tcp);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001915
Grant Edwards8a082772011-04-07 20:25:40 +00001916 if (res == 1 && filtered(tcp)) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001917 goto ret;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001918 }
1919
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001920 /* TODO: TCB_REPRINT is probably not necessary:
1921 * we can determine whether reprinting is needed
1922 * by examining printing_tcp. Something like:
1923 * if not in -ff mode, and printing_tcp != tcp,
1924 * then the log is not currenlty ends with *our*
1925 * syscall entry output, but with something else,
1926 * and we need to reprint.
1927 * If we'd implement this, printing_tcp = tcp
1928 * assignments in code below can be made more logical.
1929 */
1930
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001931 if (tcp->flags & TCB_REPRINT) {
1932 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001933 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001934 tprintf("<... syscall_%lu resumed> ", tcp->scno);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001935 else
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001936 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001937 }
1938
1939 if (cflag) {
1940 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02001941 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02001942 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001943 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001944 }
1945 }
1946
1947 if (res != 1) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001948 printing_tcp = tcp;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001949 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001950 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01001951 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001952 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001953 tcp->flags &= ~TCB_INSYSCALL;
1954 return res;
1955 }
1956
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001957 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001958 || (qual_flags[tcp->scno] & QUAL_RAW)) {
1959 printing_tcp = tcp;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001960 sys_res = printargs(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001961 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001962 /* FIXME: not_failing_only (IOW, option -z) is broken:
1963 * failure of syscall is known only after syscall return.
1964 * Thus we end up with something like this on, say, ENOENT:
1965 * open("doesnt_exist", O_RDONLY <unfinished ...>
1966 * {next syscall decode}
1967 * whereas the intended result is that open(...) line
1968 * is not shown at all.
1969 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001970 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02001971 goto ret; /* ignore failed syscalls */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001972 printing_tcp = tcp;
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;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002071 default:
2072 fprintf(stderr,
2073 "invalid rval format\n");
2074 break;
2075 }
2076 }
2077 if ((sys_res & RVAL_STR) && tcp->auxstr)
2078 tprintf(" (%s)", tcp->auxstr);
2079 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002080 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002081 tv_sub(&tv, &tv, &tcp->etime);
2082 tprintf(" <%ld.%06ld>",
2083 (long) tv.tv_sec, (long) tv.tv_usec);
2084 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002085 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002086 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002087 line_ended();
2088
Denys Vlasenko3b738812011-08-22 02:06:35 +02002089 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002090 tcp->flags &= ~TCB_INSYSCALL;
2091 return 0;
2092}
2093
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002094int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002095trace_syscall(struct tcb *tcp)
2096{
2097 return exiting(tcp) ?
2098 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2099}