blob: ac0f76999443cfa628217d3168ad598868a58078 [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);
1472 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001473 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001474 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001475 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001476 tprintf("syscall_%lu(", tcp->scno);
1477 else
1478 tprintf("%s(", sysent[tcp->scno].sys_name);
1479 /*
1480 * " <unavailable>" will be added later by the code which
1481 * detects ptrace errors.
1482 */
1483 goto ret;
1484 }
1485
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001486#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1487 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001488# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001489 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001490 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001491 break;
1492 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001493# endif
1494# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001495 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001496 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001497 break;
1498 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001499# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001500 break;
1501 }
1502#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1503
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001504 internal_syscall(tcp);
1505
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001506 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001507 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1508 (tracing_paths && !pathtrace_match(tcp))) {
1509 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1510 return 0;
1511 }
1512
1513 tcp->flags &= ~TCB_FILTERED;
1514
1515 if (cflag == CFLAG_ONLY_STATS) {
1516 res = 0;
1517 goto ret;
1518 }
1519
1520 printleader(tcp);
1521 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001522 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001523 tprintf("syscall_%lu(", tcp->scno);
1524 else
1525 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001526 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001527 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1528 sysent[tcp->scno].sys_func != sys_exit))
1529 res = printargs(tcp);
1530 else
1531 res = (*sysent[tcp->scno].sys_func)(tcp);
1532
1533 if (fflush(tcp->outf) == EOF)
1534 return -1;
1535 ret:
1536 tcp->flags |= TCB_INSYSCALL;
1537 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001538 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001539 gettimeofday(&tcp->etime, NULL);
1540 return res;
1541}
1542
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001543/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001544 * 1: ok, continue in trace_syscall_exiting().
1545 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001546 * ("????" etc) and bail out.
1547 */
1548static int
1549get_syscall_result(struct tcb *tcp)
1550{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001551#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001552 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1553 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001554#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001555# define SO_MASK 0x10000000
1556 {
1557 long flags;
1558 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1559 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001560 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001561 return -1;
1562 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001563 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001564 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001565#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001566 /* Read complete register set in one go. */
1567 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1568 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001569#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001570 if (upeek(tcp, PT_R0, &r0) < 0)
1571 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001572#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001573 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001574 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001575#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001576 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001577 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001578#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001579# define IA64_PSR_IS ((long)1 << 34)
1580 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1581 ia32 = (psr & IA64_PSR_IS) != 0;
1582 if (upeek(tcp, PT_R8, &r8) < 0)
1583 return -1;
1584 if (upeek(tcp, PT_R10, &r10) < 0)
1585 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001586#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001587 /* Read complete register set in one go. */
1588 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1589 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001590#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001591 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1592 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001593#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001594 unsigned long long regs[38];
1595
1596 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1597 return -1;
1598 a3 = regs[REG_A3];
1599 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001600#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001601 if (upeek(tcp, REG_A3, &a3) < 0)
1602 return -1;
1603 if (upeek(tcp, REG_V0, &r2) < 0)
1604 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001605#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001606 if (upeek(tcp, REG_A3, &a3) < 0)
1607 return -1;
1608 if (upeek(tcp, REG_R0, &r0) < 0)
1609 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001610#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001611 /* Everything we need is in the current register set. */
1612 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1613 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001614#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001615 if (upeek(tcp, PT_GR28, &r28) < 0)
1616 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001617#elif defined(SH)
1618#elif defined(SH64)
1619#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001620 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1621 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001622#elif defined(TILE)
1623#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001624 if (upeek(tcp, 3 * 4, &r3) < 0)
1625 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001626#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001627
Denys Vlasenko523635f2012-02-25 02:44:25 +01001628#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001629 /* new syscall ABI returns result in R0 */
1630 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1631 return -1;
1632#elif defined(SH64)
1633 /* ABI defines result returned in r9 */
1634 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1635 return -1;
1636#endif
1637
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001638 return 1;
1639}
1640
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001641/* Called at each syscall exit */
1642static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001643syscall_fixup_on_sysexit(struct tcb *tcp)
1644{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001645#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001646 if (syscall_mode != -ENOSYS)
1647 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001648 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001649 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1650 /*
1651 * Return from execve.
1652 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1653 * flag set for the post-execve SIGTRAP to see and reset.
1654 */
1655 gpr2 = 0;
1656 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001657#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001658}
1659
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001660/*
1661 * Check the syscall return value register value for whether it is
1662 * a negated errno code indicating an error, or a success return value.
1663 */
1664static inline int
1665is_negated_errno(unsigned long int val)
1666{
1667 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001668#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001669 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001670 val = (unsigned int) val;
1671 max = (unsigned int) max;
1672 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001673#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001674 return val > max;
1675}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001676
Denys Vlasenko907735a2012-03-21 00:23:16 +01001677/* Returns:
1678 * 1: ok, continue in trace_syscall_exiting().
1679 * -1: error, trace_syscall_exiting() should print error indicator
1680 * ("????" etc) and bail out.
1681 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001682static int
1683get_error(struct tcb *tcp)
1684{
1685 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001686 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001687 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001688 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1689 check_errno = 0;
1690 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001691#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001692 if (check_errno && is_negated_errno(gpr2)) {
1693 tcp->u_rval = -1;
1694 u_error = -gpr2;
1695 }
1696 else {
1697 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001698 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001699#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001700 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001701 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001702 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001703 }
1704 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001705 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001706 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001707#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001708 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001709 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001710 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001711 }
1712 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001713 tcp->u_rval = x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001714 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001715#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001716 if (ia32) {
1717 int err;
1718
1719 err = (int)r8;
1720 if (check_errno && is_negated_errno(err)) {
1721 tcp->u_rval = -1;
1722 u_error = -err;
1723 }
1724 else {
1725 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001726 }
1727 } else {
1728 if (check_errno && r10) {
1729 tcp->u_rval = -1;
1730 u_error = r8;
1731 } else {
1732 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001733 }
1734 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001735#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001736 if (check_errno && a3) {
1737 tcp->u_rval = -1;
1738 u_error = r2;
1739 } else {
1740 tcp->u_rval = r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001741 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001742#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001743 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001744 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001745 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001746 }
1747 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001748 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001749 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001750#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001751 if (check_errno && is_negated_errno(d0)) {
1752 tcp->u_rval = -1;
1753 u_error = -d0;
1754 }
1755 else {
1756 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001757 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001758#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001759 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1760 tcp->u_rval = -1;
1761 u_error = -regs.ARM_r0;
1762 }
1763 else {
1764 tcp->u_rval = regs.ARM_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001765 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001766#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001767 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1768 tcp->u_rval = -1;
1769 u_error = -regs.r12;
1770 }
1771 else {
1772 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001773 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001774#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001775 if (check_errno && is_negated_errno(r0)) {
1776 tcp->u_rval = -1;
1777 u_error = -r0;
1778 } else {
1779 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001780 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001781#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001782 if (check_errno && a3) {
1783 tcp->u_rval = -1;
1784 u_error = r0;
1785 }
1786 else {
1787 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001788 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001789#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001790 if (check_errno && regs.psr & PSR_C) {
1791 tcp->u_rval = -1;
1792 u_error = regs.u_regs[U_REG_O0];
1793 }
1794 else {
1795 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001796 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001797#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001798 if (check_errno && regs.tstate & 0x1100000000UL) {
1799 tcp->u_rval = -1;
1800 u_error = regs.u_regs[U_REG_O0];
1801 }
1802 else {
1803 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001804 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001805#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001806 if (check_errno && is_negated_errno(r28)) {
1807 tcp->u_rval = -1;
1808 u_error = -r28;
1809 }
1810 else {
1811 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001812 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001813#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001814 if (check_errno && is_negated_errno(r0)) {
1815 tcp->u_rval = -1;
1816 u_error = -r0;
1817 }
1818 else {
1819 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001820 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001821#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001822 if (check_errno && is_negated_errno(r9)) {
1823 tcp->u_rval = -1;
1824 u_error = -r9;
1825 }
1826 else {
1827 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001828 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001829#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001830 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1831 tcp->u_rval = -1;
1832 u_error = -r10;
1833 }
1834 else {
1835 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001836 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001837#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001838 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001839 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1840 return -1;
1841 if (check_errno && rval < 0 && rval > -nerrnos) {
1842 tcp->u_rval = -1;
1843 u_error = -rval;
1844 }
1845 else {
1846 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001847 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001848#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001849 if (check_errno && is_negated_errno(r3)) {
1850 tcp->u_rval = -1;
1851 u_error = -r3;
1852 }
1853 else {
1854 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001855 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001856#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001857 tcp->u_error = u_error;
1858 return 1;
1859}
1860
1861static void
1862dumpio(struct tcb *tcp)
1863{
1864 if (syserror(tcp))
1865 return;
1866 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1867 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001868 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001869 return;
1870 if (sysent[tcp->scno].sys_func == printargs)
1871 return;
1872 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1873 if (sysent[tcp->scno].sys_func == sys_read ||
1874 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001875 sysent[tcp->scno].sys_func == sys_recv ||
1876 sysent[tcp->scno].sys_func == sys_recvfrom)
1877 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1878 else if (sysent[tcp->scno].sys_func == sys_readv)
1879 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1880 return;
1881 }
1882 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1883 if (sysent[tcp->scno].sys_func == sys_write ||
1884 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001885 sysent[tcp->scno].sys_func == sys_send ||
1886 sysent[tcp->scno].sys_func == sys_sendto)
1887 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1888 else if (sysent[tcp->scno].sys_func == sys_writev)
1889 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1890 return;
1891 }
1892}
1893
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001894static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001895trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001896{
1897 int sys_res;
1898 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001899 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001900 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001901
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001902 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001903 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001904 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001905
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001906#if SUPPORTED_PERSONALITIES > 1
1907 update_personality(tcp, tcp->currpers);
1908#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001909 res = get_syscall_result(tcp);
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001910 if (res == 1) {
1911 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01001912 res = get_error(tcp); /* returns 1 or -1 */
1913 if (res == 1) {
1914 internal_syscall(tcp);
1915 if (filtered(tcp)) {
1916 goto ret;
1917 }
1918 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00001919 }
1920
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001921 /* TODO: TCB_REPRINT is probably not necessary:
1922 * we can determine whether reprinting is needed
1923 * by examining printing_tcp. Something like:
1924 * if not in -ff mode, and printing_tcp != tcp,
Denys Vlasenko907735a2012-03-21 00:23:16 +01001925 * then the log is not currently ends with *our*
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001926 * syscall entry output, but with something else,
1927 * and we need to reprint.
1928 * If we'd implement this, printing_tcp = tcp
1929 * assignments in code below can be made more logical.
1930 */
1931
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001932 if (tcp->flags & TCB_REPRINT) {
1933 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001934 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001935 tprintf("<... syscall_%lu resumed> ", tcp->scno);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001936 else
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001937 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001938 }
1939
1940 if (cflag) {
1941 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02001942 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02001943 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001944 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001945 }
1946 }
1947
1948 if (res != 1) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001949 printing_tcp = tcp;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001950 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001951 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01001952 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001953 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001954 tcp->flags &= ~TCB_INSYSCALL;
1955 return res;
1956 }
1957
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001958 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001959 || (qual_flags[tcp->scno] & QUAL_RAW)) {
1960 printing_tcp = tcp;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001961 sys_res = printargs(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001962 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001963 /* FIXME: not_failing_only (IOW, option -z) is broken:
1964 * failure of syscall is known only after syscall return.
1965 * Thus we end up with something like this on, say, ENOENT:
1966 * open("doesnt_exist", O_RDONLY <unfinished ...>
1967 * {next syscall decode}
1968 * whereas the intended result is that open(...) line
1969 * is not shown at all.
1970 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001971 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02001972 goto ret; /* ignore failed syscalls */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001973 printing_tcp = tcp;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001974 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
1975 }
1976
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001977 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001978 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02001979 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001980 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001981 qual_flags[tcp->scno] & QUAL_RAW) {
1982 if (u_error)
1983 tprintf("= -1 (errno %ld)", u_error);
1984 else
1985 tprintf("= %#lx", tcp->u_rval);
1986 }
1987 else if (!(sys_res & RVAL_NONE) && u_error) {
1988 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01001989 /* Blocked signals do not interrupt any syscalls.
1990 * In this case syscalls don't return ERESTARTfoo codes.
1991 *
1992 * Deadly signals set to SIG_DFL interrupt syscalls
1993 * and kill the process regardless of which of the codes below
1994 * is returned by the interrupted syscall.
1995 * In some cases, kernel forces a kernel-generated deadly
1996 * signal to be unblocked and set to SIG_DFL (and thus cause
1997 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
1998 * or SIGILL. (The alternative is to leave process spinning
1999 * forever on the faulty instruction - not useful).
2000 *
2001 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2002 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2003 * but kernel will always restart them.
2004 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002005 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002006 /* Most common type of signal-interrupted syscall exit code.
2007 * The system call will be restarted with the same arguments
2008 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2009 */
2010 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002011 break;
2012 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002013 /* Rare. For example, fork() returns this if interrupted.
2014 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2015 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002016 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002017 break;
2018 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002019 /* pause(), rt_sigsuspend() etc use this code.
2020 * SA_RESTART is ignored (assumed not set):
2021 * syscall won't restart (will return EINTR instead)
2022 * even after signal with SA_RESTART set.
2023 * However, after SIG_IGN or SIG_DFL signal it will.
2024 */
2025 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002026 break;
2027 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002028 /* Syscalls like nanosleep(), poll() which can't be
2029 * restarted with their original arguments use this
2030 * code. Kernel will execute restart_syscall() instead,
2031 * which changes arguments before restarting syscall.
2032 * SA_RESTART is ignored (assumed not set) similarly
2033 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2034 * since restart data is saved in "restart block"
2035 * in task struct, and if signal handler uses a syscall
2036 * which in turn saves another such restart block,
2037 * old data is lost and restart becomes impossible)
2038 */
2039 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002040 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002041 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002042 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002043 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002044 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002045 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002046 strerror(u_error));
2047 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002048 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002049 strerror(u_error));
2050 break;
2051 }
2052 if ((sys_res & RVAL_STR) && tcp->auxstr)
2053 tprintf(" (%s)", tcp->auxstr);
2054 }
2055 else {
2056 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002057 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002058 else {
2059 switch (sys_res & RVAL_MASK) {
2060 case RVAL_HEX:
2061 tprintf("= %#lx", tcp->u_rval);
2062 break;
2063 case RVAL_OCTAL:
2064 tprintf("= %#lo", tcp->u_rval);
2065 break;
2066 case RVAL_UDECIMAL:
2067 tprintf("= %lu", tcp->u_rval);
2068 break;
2069 case RVAL_DECIMAL:
2070 tprintf("= %ld", tcp->u_rval);
2071 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002072 default:
2073 fprintf(stderr,
2074 "invalid rval format\n");
2075 break;
2076 }
2077 }
2078 if ((sys_res & RVAL_STR) && tcp->auxstr)
2079 tprintf(" (%s)", tcp->auxstr);
2080 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002081 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002082 tv_sub(&tv, &tv, &tcp->etime);
2083 tprintf(" <%ld.%06ld>",
2084 (long) tv.tv_sec, (long) tv.tv_usec);
2085 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002086 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002087 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002088 line_ended();
2089
Denys Vlasenko3b738812011-08-22 02:06:35 +02002090 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002091 tcp->flags &= ~TCB_INSYSCALL;
2092 return 0;
2093}
2094
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002095int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002096trace_syscall(struct tcb *tcp)
2097{
2098 return exiting(tcp) ?
2099 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2100}