blob: 663d678b841608cfb6085fad8e750f8d38c675fb [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 Vlasenko46dc8b22012-03-21 00:07:25 +0100638static long ppc_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:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100676 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
677 * 1: ok, continue in trace_syscall_entering().
678 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200679 * ("????" 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 Vlasenko907735a2012-03-21 00:23:16 +01001085 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1086 * 1: ok, continue in trace_syscall_entering().
1087 * other: error, trace_syscall_entering() 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;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001462 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001463 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001464 if (res == 0)
1465 return res;
1466 if (res == 1)
1467 res = get_syscall_args(tcp);
1468 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001469
1470 if (res != 1) {
1471 printleader(tcp);
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);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001520 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001521 tprintf("syscall_%lu(", tcp->scno);
1522 else
1523 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001524 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001525 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1526 sysent[tcp->scno].sys_func != sys_exit))
1527 res = printargs(tcp);
1528 else
1529 res = (*sysent[tcp->scno].sys_func)(tcp);
1530
1531 if (fflush(tcp->outf) == EOF)
1532 return -1;
1533 ret:
1534 tcp->flags |= TCB_INSYSCALL;
1535 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001536 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001537 gettimeofday(&tcp->etime, NULL);
1538 return res;
1539}
1540
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001541/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001542 * 1: ok, continue in trace_syscall_exiting().
1543 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001544 * ("????" etc) and bail out.
1545 */
1546static int
1547get_syscall_result(struct tcb *tcp)
1548{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001549#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001550 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1551 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001552#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001553# define SO_MASK 0x10000000
1554 {
1555 long flags;
1556 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1557 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001558 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001559 return -1;
1560 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001561 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001562 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001563#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001564 /* Read complete register set in one go. */
1565 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1566 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001567#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001568 if (upeek(tcp, PT_R0, &r0) < 0)
1569 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001570#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001571 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001572 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001573#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001574 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001575 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001576#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001577# define IA64_PSR_IS ((long)1 << 34)
1578 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1579 ia32 = (psr & IA64_PSR_IS) != 0;
1580 if (upeek(tcp, PT_R8, &r8) < 0)
1581 return -1;
1582 if (upeek(tcp, PT_R10, &r10) < 0)
1583 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001584#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001585 /* Read complete register set in one go. */
1586 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1587 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001588#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001589 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1590 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001591#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001592 unsigned long long regs[38];
1593
1594 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1595 return -1;
1596 a3 = regs[REG_A3];
1597 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001598#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001599 if (upeek(tcp, REG_A3, &a3) < 0)
1600 return -1;
1601 if (upeek(tcp, REG_V0, &r2) < 0)
1602 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001603#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001604 if (upeek(tcp, REG_A3, &a3) < 0)
1605 return -1;
1606 if (upeek(tcp, REG_R0, &r0) < 0)
1607 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001608#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001609 /* Everything we need is in the current register set. */
1610 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1611 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001612#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001613 if (upeek(tcp, PT_GR28, &r28) < 0)
1614 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001615#elif defined(SH)
1616#elif defined(SH64)
1617#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001618 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1619 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001620#elif defined(TILE)
1621#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001622 if (upeek(tcp, 3 * 4, &r3) < 0)
1623 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001624#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001625
Denys Vlasenko523635f2012-02-25 02:44:25 +01001626#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001627 /* new syscall ABI returns result in R0 */
1628 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1629 return -1;
1630#elif defined(SH64)
1631 /* ABI defines result returned in r9 */
1632 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1633 return -1;
1634#endif
1635
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001636 return 1;
1637}
1638
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001639/* Called at each syscall exit */
1640static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001641syscall_fixup_on_sysexit(struct tcb *tcp)
1642{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001643#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001644 if (syscall_mode != -ENOSYS)
1645 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001646 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001647 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1648 /*
1649 * Return from execve.
1650 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1651 * flag set for the post-execve SIGTRAP to see and reset.
1652 */
1653 gpr2 = 0;
1654 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001655#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001656}
1657
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001658/*
1659 * Check the syscall return value register value for whether it is
1660 * a negated errno code indicating an error, or a success return value.
1661 */
1662static inline int
1663is_negated_errno(unsigned long int val)
1664{
1665 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001666#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001667 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001668 val = (unsigned int) val;
1669 max = (unsigned int) max;
1670 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001671#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001672 return val > max;
1673}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001674
Denys Vlasenko907735a2012-03-21 00:23:16 +01001675/* Returns:
1676 * 1: ok, continue in trace_syscall_exiting().
1677 * -1: error, trace_syscall_exiting() should print error indicator
1678 * ("????" etc) and bail out.
1679 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001680static int
1681get_error(struct tcb *tcp)
1682{
1683 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001684 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001685 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001686 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1687 check_errno = 0;
1688 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001689#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001690 if (check_errno && is_negated_errno(gpr2)) {
1691 tcp->u_rval = -1;
1692 u_error = -gpr2;
1693 }
1694 else {
1695 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001696 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001697#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001698 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001699 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001700 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001701 }
1702 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001703 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001704 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001705#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001706 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001707 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001708 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001709 }
1710 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001711 tcp->u_rval = x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001712 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001713#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001714 if (ia32) {
1715 int err;
1716
1717 err = (int)r8;
1718 if (check_errno && is_negated_errno(err)) {
1719 tcp->u_rval = -1;
1720 u_error = -err;
1721 }
1722 else {
1723 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001724 }
1725 } else {
1726 if (check_errno && r10) {
1727 tcp->u_rval = -1;
1728 u_error = r8;
1729 } else {
1730 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001731 }
1732 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001733#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001734 if (check_errno && a3) {
1735 tcp->u_rval = -1;
1736 u_error = r2;
1737 } else {
1738 tcp->u_rval = r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001739 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001740#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001741 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001742 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001743 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001744 }
1745 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001746 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001747 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001748#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001749 if (check_errno && is_negated_errno(d0)) {
1750 tcp->u_rval = -1;
1751 u_error = -d0;
1752 }
1753 else {
1754 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001755 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001756#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001757 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1758 tcp->u_rval = -1;
1759 u_error = -regs.ARM_r0;
1760 }
1761 else {
1762 tcp->u_rval = regs.ARM_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001763 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001764#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001765 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1766 tcp->u_rval = -1;
1767 u_error = -regs.r12;
1768 }
1769 else {
1770 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001771 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001772#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001773 if (check_errno && is_negated_errno(r0)) {
1774 tcp->u_rval = -1;
1775 u_error = -r0;
1776 } else {
1777 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001778 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001779#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001780 if (check_errno && a3) {
1781 tcp->u_rval = -1;
1782 u_error = r0;
1783 }
1784 else {
1785 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001786 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001787#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001788 if (check_errno && regs.psr & PSR_C) {
1789 tcp->u_rval = -1;
1790 u_error = regs.u_regs[U_REG_O0];
1791 }
1792 else {
1793 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001794 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001795#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001796 if (check_errno && regs.tstate & 0x1100000000UL) {
1797 tcp->u_rval = -1;
1798 u_error = regs.u_regs[U_REG_O0];
1799 }
1800 else {
1801 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001802 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001803#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001804 if (check_errno && is_negated_errno(r28)) {
1805 tcp->u_rval = -1;
1806 u_error = -r28;
1807 }
1808 else {
1809 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001810 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001811#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001812 if (check_errno && is_negated_errno(r0)) {
1813 tcp->u_rval = -1;
1814 u_error = -r0;
1815 }
1816 else {
1817 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001818 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001819#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001820 if (check_errno && is_negated_errno(r9)) {
1821 tcp->u_rval = -1;
1822 u_error = -r9;
1823 }
1824 else {
1825 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001826 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001827#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001828 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1829 tcp->u_rval = -1;
1830 u_error = -r10;
1831 }
1832 else {
1833 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001834 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001835#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001836 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001837 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1838 return -1;
1839 if (check_errno && rval < 0 && rval > -nerrnos) {
1840 tcp->u_rval = -1;
1841 u_error = -rval;
1842 }
1843 else {
1844 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001845 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001846#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001847 if (check_errno && is_negated_errno(r3)) {
1848 tcp->u_rval = -1;
1849 u_error = -r3;
1850 }
1851 else {
1852 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001853 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001854#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001855 tcp->u_error = u_error;
1856 return 1;
1857}
1858
1859static void
1860dumpio(struct tcb *tcp)
1861{
1862 if (syserror(tcp))
1863 return;
1864 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1865 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001866 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001867 return;
1868 if (sysent[tcp->scno].sys_func == printargs)
1869 return;
1870 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1871 if (sysent[tcp->scno].sys_func == sys_read ||
1872 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001873 sysent[tcp->scno].sys_func == sys_recv ||
1874 sysent[tcp->scno].sys_func == sys_recvfrom)
1875 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1876 else if (sysent[tcp->scno].sys_func == sys_readv)
1877 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1878 return;
1879 }
1880 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1881 if (sysent[tcp->scno].sys_func == sys_write ||
1882 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001883 sysent[tcp->scno].sys_func == sys_send ||
1884 sysent[tcp->scno].sys_func == sys_sendto)
1885 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1886 else if (sysent[tcp->scno].sys_func == sys_writev)
1887 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1888 return;
1889 }
1890}
1891
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001892static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001893trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001894{
1895 int sys_res;
1896 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001897 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001898 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001899
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001900 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001901 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001902 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001903
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001904#if SUPPORTED_PERSONALITIES > 1
1905 update_personality(tcp, tcp->currpers);
1906#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001907 res = get_syscall_result(tcp);
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001908 if (res == 1) {
1909 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01001910 res = get_error(tcp); /* returns 1 or -1 */
1911 if (res == 1) {
1912 internal_syscall(tcp);
1913 if (filtered(tcp)) {
1914 goto ret;
1915 }
1916 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00001917 }
1918
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001919 if (cflag) {
1920 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02001921 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02001922 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001923 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001924 }
1925 }
1926
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01001927 /* If not in -ff mode, and printing_tcp != tcp,
1928 * then the log currently does not end with output
1929 * of _our syscall entry_, but with something else.
1930 * We need to say which syscall's return is this.
1931 *
1932 * Forced reprinting via TCB_REPRINT is used only by
1933 * "strace -ff -oLOG test/threaded_execve" corner case.
1934 * It's the only case when -ff mode needs reprinting.
1935 */
1936 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
1937 tcp->flags &= ~TCB_REPRINT;
1938 printleader(tcp);
1939 if (!SCNO_IN_RANGE(tcp->scno))
1940 tprintf("<... syscall_%lu resumed> ", tcp->scno);
1941 else
1942 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
1943 }
1944 printing_tcp = tcp;
1945
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001946 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01001947 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001948 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001949 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01001950 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001951 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001952 tcp->flags &= ~TCB_INSYSCALL;
1953 return res;
1954 }
1955
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01001956 sys_res = 0;
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)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01001959 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001960 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001961 /* FIXME: not_failing_only (IOW, option -z) is broken:
1962 * failure of syscall is known only after syscall return.
1963 * Thus we end up with something like this on, say, ENOENT:
1964 * open("doesnt_exist", O_RDONLY <unfinished ...>
1965 * {next syscall decode}
1966 * whereas the intended result is that open(...) line
1967 * is not shown at all.
1968 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001969 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02001970 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001971 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
1972 }
1973
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001974 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001975 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02001976 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001977 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001978 qual_flags[tcp->scno] & QUAL_RAW) {
1979 if (u_error)
1980 tprintf("= -1 (errno %ld)", u_error);
1981 else
1982 tprintf("= %#lx", tcp->u_rval);
1983 }
1984 else if (!(sys_res & RVAL_NONE) && u_error) {
1985 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01001986 /* Blocked signals do not interrupt any syscalls.
1987 * In this case syscalls don't return ERESTARTfoo codes.
1988 *
1989 * Deadly signals set to SIG_DFL interrupt syscalls
1990 * and kill the process regardless of which of the codes below
1991 * is returned by the interrupted syscall.
1992 * In some cases, kernel forces a kernel-generated deadly
1993 * signal to be unblocked and set to SIG_DFL (and thus cause
1994 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
1995 * or SIGILL. (The alternative is to leave process spinning
1996 * forever on the faulty instruction - not useful).
1997 *
1998 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
1999 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2000 * but kernel will always restart them.
2001 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002002 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002003 /* Most common type of signal-interrupted syscall exit code.
2004 * The system call will be restarted with the same arguments
2005 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2006 */
2007 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002008 break;
2009 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002010 /* Rare. For example, fork() returns this if interrupted.
2011 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2012 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002013 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002014 break;
2015 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002016 /* pause(), rt_sigsuspend() etc use this code.
2017 * SA_RESTART is ignored (assumed not set):
2018 * syscall won't restart (will return EINTR instead)
2019 * even after signal with SA_RESTART set.
2020 * However, after SIG_IGN or SIG_DFL signal it will.
2021 */
2022 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002023 break;
2024 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002025 /* Syscalls like nanosleep(), poll() which can't be
2026 * restarted with their original arguments use this
2027 * code. Kernel will execute restart_syscall() instead,
2028 * which changes arguments before restarting syscall.
2029 * SA_RESTART is ignored (assumed not set) similarly
2030 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2031 * since restart data is saved in "restart block"
2032 * in task struct, and if signal handler uses a syscall
2033 * which in turn saves another such restart block,
2034 * old data is lost and restart becomes impossible)
2035 */
2036 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002037 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002038 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002039 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002040 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002041 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002042 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002043 strerror(u_error));
2044 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002045 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002046 strerror(u_error));
2047 break;
2048 }
2049 if ((sys_res & RVAL_STR) && tcp->auxstr)
2050 tprintf(" (%s)", tcp->auxstr);
2051 }
2052 else {
2053 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002054 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002055 else {
2056 switch (sys_res & RVAL_MASK) {
2057 case RVAL_HEX:
2058 tprintf("= %#lx", tcp->u_rval);
2059 break;
2060 case RVAL_OCTAL:
2061 tprintf("= %#lo", tcp->u_rval);
2062 break;
2063 case RVAL_UDECIMAL:
2064 tprintf("= %lu", tcp->u_rval);
2065 break;
2066 case RVAL_DECIMAL:
2067 tprintf("= %ld", tcp->u_rval);
2068 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002069 default:
2070 fprintf(stderr,
2071 "invalid rval format\n");
2072 break;
2073 }
2074 }
2075 if ((sys_res & RVAL_STR) && tcp->auxstr)
2076 tprintf(" (%s)", tcp->auxstr);
2077 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002078 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002079 tv_sub(&tv, &tv, &tcp->etime);
2080 tprintf(" <%ld.%06ld>",
2081 (long) tv.tv_sec, (long) tv.tv_usec);
2082 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002083 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002084 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002085 line_ended();
2086
Denys Vlasenko3b738812011-08-22 02:06:35 +02002087 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002088 tcp->flags &= ~TCB_INSYSCALL;
2089 return 0;
2090}
2091
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002092int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002093trace_syscall(struct tcb *tcp)
2094{
2095 return exiting(tcp) ?
2096 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2097}