blob: dce705641328f02ecaf2c7a21a283bbef8ef60ea [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.
32 *
33 * $Id$
34 */
35
36#include "defs.h"
37
38#include <signal.h>
39#include <time.h>
40#include <errno.h>
41#include <sys/user.h>
42#include <sys/syscall.h>
43#include <sys/param.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000044
Wichert Akkerman15dea971999-10-06 13:06:34 +000045#ifdef HAVE_SYS_REG_H
Denys Vlasenko523635f2012-02-25 02:44:25 +010046# include <sys/reg.h>
47# ifndef PTRACE_PEEKUSR
48# define PTRACE_PEEKUSR PTRACE_PEEKUSER
49# endif
Wichert Akkermanfaf72222000-02-19 23:59:03 +000050#elif defined(HAVE_LINUX_PTRACE_H)
Denys Vlasenko523635f2012-02-25 02:44:25 +010051# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000052# ifdef HAVE_STRUCT_IA64_FPREG
53# define ia64_fpreg XXX_ia64_fpreg
54# endif
55# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
56# define pt_all_user_regs XXX_pt_all_user_regs
57# endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010058# include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000059# undef ia64_fpreg
60# undef pt_all_user_regs
Wichert Akkerman15dea971999-10-06 13:06:34 +000061#endif
62
Denys Vlasenko84703742012-02-25 02:38:52 +010063#if defined(SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +000064# undef PTRACE_GETREGS
65# define PTRACE_GETREGS PTRACE_GETREGS64
66# undef PTRACE_SETREGS
67# define PTRACE_SETREGS PTRACE_SETREGS64
Denys Vlasenko84703742012-02-25 02:38:52 +010068#endif
Roland McGrath6d1a65c2004-07-12 07:44:08 +000069
Denys Vlasenko84703742012-02-25 02:38:52 +010070#if defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000071# include <asm/ptrace_offsets.h>
72# include <asm/rse.h>
73#endif
74
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000075#ifndef ERESTARTSYS
Denys Vlasenko523635f2012-02-25 02:44:25 +010076# define ERESTARTSYS 512
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000077#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010078# ifndef ERESTARTNOINTR
79# define ERESTARTNOINTR 513
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000080#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010081# ifndef ERESTARTNOHAND
82# define ERESTARTNOHAND 514 /* restart if no handler.. */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000083#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010084# ifndef ENOIOCTLCMD
85# define ENOIOCTLCMD 515 /* No ioctl command */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000086#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010087# ifndef ERESTART_RESTARTBLOCK
88# define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
Roland McGrath9c555e72003-07-09 09:47:59 +000089#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010090
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000091#ifndef NSIG
Denys Vlasenko523635f2012-02-25 02:44:25 +010092# warning: NSIG is not defined, using 32
93# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000094#endif
95#ifdef ARM
Denys Vlasenko041b3ee2011-08-18 12:48:56 +020096/* Ugh. Is this really correct? ARM has no RT signals?! */
Denys Vlasenko523635f2012-02-25 02:44:25 +010097# undef NSIG
98# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000099#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000100
101#include "syscall.h"
102
103/* Define these shorthand notations to simplify the syscallent files. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000104#define TD TRACE_DESC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000105#define TF TRACE_FILE
106#define TI TRACE_IPC
107#define TN TRACE_NETWORK
108#define TP TRACE_PROCESS
109#define TS TRACE_SIGNAL
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000110#define NF SYSCALL_NEVER_FAILS
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200111#define MA MAX_ARGS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000112
Roland McGrathee36ce12004-09-04 03:53:10 +0000113static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000114#include "syscallent.h"
115};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000116
117#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000118static const struct sysent sysent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100119# include "syscallent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200121#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122
123#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000124static const struct sysent sysent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100125# include "syscallent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000126};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200127#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000128
129/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000130#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000131#undef TF
132#undef TI
133#undef TN
134#undef TP
135#undef TS
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000136#undef NF
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200137#undef MA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000138
Denys Vlasenko39fca622011-08-20 02:12:33 +0200139/*
140 * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
141 * program `ioctlsort', such that the list is sorted by the `code' field.
142 * This has the side-effect of resolving the _IO.. macros into
143 * plain integers, eliminating the need to include here everything
144 * in "/usr/include".
145 */
146
Roland McGrathee36ce12004-09-04 03:53:10 +0000147static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000148#include "errnoent.h"
149};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200150static const char *const signalent0[] = {
151#include "signalent.h"
152};
153static const struct ioctlent ioctlent0[] = {
154#include "ioctlent.h"
155};
156enum { nsyscalls0 = ARRAY_SIZE(sysent0) };
157enum { nerrnos0 = ARRAY_SIZE(errnoent0) };
158enum { nsignals0 = ARRAY_SIZE(signalent0) };
159enum { nioctlents0 = ARRAY_SIZE(ioctlent0) };
160int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000161
162#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000163static const char *const errnoent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100164# include "errnoent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000165};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200166static const char *const signalent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100167# include "signalent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200168};
169static const struct ioctlent ioctlent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100170# include "ioctlent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200171};
172enum { nsyscalls1 = ARRAY_SIZE(sysent1) };
173enum { nerrnos1 = ARRAY_SIZE(errnoent1) };
174enum { nsignals1 = ARRAY_SIZE(signalent1) };
175enum { nioctlents1 = ARRAY_SIZE(ioctlent1) };
176int qual_flags1[MAX_QUALS];
177#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000178
179#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000180static const char *const errnoent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100181# include "errnoent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000182};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200183static const char *const signalent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100184# include "signalent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200185};
186static const struct ioctlent ioctlent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100187# include "ioctlent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200188};
189enum { nsyscalls2 = ARRAY_SIZE(sysent2) };
190enum { nerrnos2 = ARRAY_SIZE(errnoent2) };
191enum { nsignals2 = ARRAY_SIZE(signalent2) };
192enum { nioctlents2 = ARRAY_SIZE(ioctlent2) };
193int qual_flags2[MAX_QUALS];
194#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000195
Denys Vlasenko39fca622011-08-20 02:12:33 +0200196const struct sysent *sysent;
Roland McGrathee36ce12004-09-04 03:53:10 +0000197const char *const *errnoent;
Denys Vlasenko39fca622011-08-20 02:12:33 +0200198const char *const *signalent;
199const struct ioctlent *ioctlent;
Denys Vlasenkoafc64032011-08-23 13:29:01 +0200200unsigned nsyscalls;
201unsigned nerrnos;
202unsigned nsignals;
203unsigned nioctlents;
Denys Vlasenko39fca622011-08-20 02:12:33 +0200204int *qual_flags;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000205
206int current_personality;
207
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000208#ifndef PERSONALITY0_WORDSIZE
209# define PERSONALITY0_WORDSIZE sizeof(long)
210#endif
211const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
212 PERSONALITY0_WORDSIZE,
213#if SUPPORTED_PERSONALITIES > 1
214 PERSONALITY1_WORDSIZE,
215#endif
216#if SUPPORTED_PERSONALITIES > 2
217 PERSONALITY2_WORDSIZE,
218#endif
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200219};
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000220
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200221void
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000222set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000223{
224 switch (personality) {
225 case 0:
226 errnoent = errnoent0;
227 nerrnos = nerrnos0;
228 sysent = sysent0;
229 nsyscalls = nsyscalls0;
230 ioctlent = ioctlent0;
231 nioctlents = nioctlents0;
232 signalent = signalent0;
233 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000234 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000235 break;
236
237#if SUPPORTED_PERSONALITIES >= 2
238 case 1:
239 errnoent = errnoent1;
240 nerrnos = nerrnos1;
241 sysent = sysent1;
242 nsyscalls = nsyscalls1;
243 ioctlent = ioctlent1;
244 nioctlents = nioctlents1;
245 signalent = signalent1;
246 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000247 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000248 break;
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200249#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000250
251#if SUPPORTED_PERSONALITIES >= 3
252 case 2:
253 errnoent = errnoent2;
254 nerrnos = nerrnos2;
255 sysent = sysent2;
256 nsyscalls = nsyscalls2;
257 ioctlent = ioctlent2;
258 nioctlents = nioctlents2;
259 signalent = signalent2;
260 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000261 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000262 break;
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200263#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000264 }
265
266 current_personality = personality;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000267}
268
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000269#if SUPPORTED_PERSONALITIES > 1
270static void
271update_personality(struct tcb *tcp, int personality)
272{
273 if (personality == current_personality)
274 return;
275 set_personality(personality);
276
277 if (personality == tcp->currpers)
278 return;
279 tcp->currpers = personality;
280
Denys Vlasenko523635f2012-02-25 02:44:25 +0100281# if defined(POWERPC64) || defined(X86_64)
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000282 if (!qflag) {
283 static const char *const names[] = {"64 bit", "32 bit"};
284 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
285 tcp->pid, names[personality]);
286 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100287# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000288}
289#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000290
Roland McGrath9797ceb2002-12-30 10:23:00 +0000291static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000292
Roland McGrathe10e62a2004-09-04 04:20:43 +0000293static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000294 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000295 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000296 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000297 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000298} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000299 { QUAL_TRACE, "trace", qual_syscall, "system call" },
300 { QUAL_TRACE, "t", qual_syscall, "system call" },
301 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
302 { QUAL_ABBREV, "a", qual_syscall, "system call" },
303 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
304 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
305 { QUAL_RAW, "raw", qual_syscall, "system call" },
306 { QUAL_RAW, "x", qual_syscall, "system call" },
307 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
308 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
309 { QUAL_SIGNAL, "s", qual_signal, "signal" },
310 { QUAL_FAULT, "fault", qual_fault, "fault" },
311 { QUAL_FAULT, "faults", qual_fault, "fault" },
312 { QUAL_FAULT, "m", qual_fault, "fault" },
313 { QUAL_READ, "read", qual_desc, "descriptor" },
314 { QUAL_READ, "reads", qual_desc, "descriptor" },
315 { QUAL_READ, "r", qual_desc, "descriptor" },
316 { QUAL_WRITE, "write", qual_desc, "descriptor" },
317 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
318 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000319 { 0, NULL, NULL, NULL },
320};
321
Roland McGrath9797ceb2002-12-30 10:23:00 +0000322static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000323qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000324{
Roland McGrath138c6a32006-01-12 09:50:49 +0000325 if (pers == 0 || pers < 0) {
326 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000327 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000328 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000329 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000330 }
331
332#if SUPPORTED_PERSONALITIES >= 2
333 if (pers == 1 || pers < 0) {
334 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000335 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000336 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000337 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000338 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100339#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000340
341#if SUPPORTED_PERSONALITIES >= 3
342 if (pers == 2 || pers < 0) {
343 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000344 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000345 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000346 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000347 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100348#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000349}
350
351static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000352qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000353{
354 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000355 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000356
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000357 if (isdigit((unsigned char)*s)) {
358 int i = atoi(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000359 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000360 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000361 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000362 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000363 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000364 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000365 if (strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000366 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000367 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000368 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000369
370#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000371 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000372 if (strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000373 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000374 rc = 0;
375 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100376#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000377
378#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000379 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000380 if (strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000381 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000382 rc = 0;
383 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100384#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000385
Roland McGrathfe6b3522005-02-02 04:40:11 +0000386 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000387}
388
389static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000390qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000391{
392 int i;
393 char buf[32];
394
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000395 if (isdigit((unsigned char)*s)) {
396 int signo = atoi(s);
397 if (signo < 0 || signo >= MAX_QUALS)
398 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000399 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000400 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000401 }
Roland McGrathd62b6712004-03-02 06:52:01 +0000402 if (strlen(s) >= sizeof buf)
Roland McGrathfe6b3522005-02-02 04:40:11 +0000403 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000404 strcpy(buf, s);
405 s = buf;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000406 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000407 s += 3;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000408 for (i = 0; i <= NSIG; i++)
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000409 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000410 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000411 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000412 }
Roland McGrath76421df2005-02-02 03:51:18 +0000413 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000414}
415
416static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000417qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000418{
419 return -1;
420}
421
422static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000423qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000424{
Roland McGrath48a035f2006-01-12 09:45:56 +0000425 if (isdigit((unsigned char)*s)) {
Roland McGrathfe6b3522005-02-02 04:40:11 +0000426 int desc = atoi(s);
427 if (desc < 0 || desc >= MAX_QUALS)
428 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000429 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000430 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000431 }
432 return -1;
433}
434
435static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000436lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000437{
438 if (strcmp(s, "file") == 0)
439 return TRACE_FILE;
440 if (strcmp(s, "ipc") == 0)
441 return TRACE_IPC;
442 if (strcmp(s, "network") == 0)
443 return TRACE_NETWORK;
444 if (strcmp(s, "process") == 0)
445 return TRACE_PROCESS;
446 if (strcmp(s, "signal") == 0)
447 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000448 if (strcmp(s, "desc") == 0)
449 return TRACE_DESC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000450 return -1;
451}
452
453void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000454qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000455{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000456 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000457 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000458 char *copy;
459 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000460 int i, n;
461
462 opt = &qual_options[0];
463 for (i = 0; (p = qual_options[i].option_name); i++) {
464 n = strlen(p);
465 if (strncmp(s, p, n) == 0 && s[n] == '=') {
466 opt = &qual_options[i];
467 s += n + 1;
468 break;
469 }
470 }
471 not = 0;
472 if (*s == '!') {
473 not = 1;
474 s++;
475 }
476 if (strcmp(s, "none") == 0) {
477 not = 1 - not;
478 s = "all";
479 }
480 if (strcmp(s, "all") == 0) {
481 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000482 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000483 }
484 return;
485 }
486 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000487 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000488 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200489 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200490 if (!copy)
491 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000492 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000493 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000494 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000495 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000496 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000497
498#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000499 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000500 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000501 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100502#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000503
504#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000505 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000506 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000507 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100508#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000509
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000510 continue;
511 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000512 if (opt->qualify(p, opt->bitflag, not)) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000513 fprintf(stderr, "strace: invalid %s `%s'\n",
514 opt->argument_name, p);
515 exit(1);
516 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000517 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000518 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000519 return;
520}
521
Wichert Akkerman8829a551999-06-11 13:18:40 +0000522enum subcall_style { shift_style, deref_style, mask_style, door_style };
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000523
Denys Vlasenko84703742012-02-25 02:38:52 +0100524#if !(defined(ALPHA) || defined(MIPS) || defined(__ARM_EABI__))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000525
Roland McGratha4d48532005-06-08 20:45:28 +0000526static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200527decode_subcall(struct tcb *tcp, int subcall, int nsubcalls, enum subcall_style style)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000528{
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000529 unsigned long addr, mask;
Denys Vlasenko4b887a52011-08-23 13:32:38 +0200530 int i, n;
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000531 int size = personality_wordsize[current_personality];
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000532
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000533 switch (style) {
534 case shift_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000535 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
536 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000537 tcp->scno = subcall + tcp->u_arg[0];
Denys Vlasenko4b887a52011-08-23 13:32:38 +0200538 tcp->u_nargs = n = sysent[tcp->scno].nargs;
539 for (i = 0; i < n; i++)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000540 tcp->u_arg[i] = tcp->u_arg[i + 1];
541 break;
542 case deref_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000543 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
544 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000545 tcp->scno = subcall + tcp->u_arg[0];
546 addr = tcp->u_arg[1];
Denys Vlasenko4b887a52011-08-23 13:32:38 +0200547 tcp->u_nargs = n = sysent[tcp->scno].nargs;
548 for (i = 0; i < n; i++) {
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000549 if (size == sizeof(int)) {
550 unsigned int arg;
551 if (umove(tcp, addr, &arg) < 0)
552 arg = 0;
553 tcp->u_arg[i] = arg;
554 }
555 else if (size == sizeof(long)) {
556 unsigned long arg;
557 if (umove(tcp, addr, &arg) < 0)
558 arg = 0;
559 tcp->u_arg[i] = arg;
560 }
561 else
562 abort();
563 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000564 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000565 break;
566 case mask_style:
567 mask = (tcp->u_arg[0] >> 8) & 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000568 for (i = 0; mask; i++)
569 mask >>= 1;
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000570 if (i >= nsubcalls)
571 return;
572 tcp->u_arg[0] &= 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000573 tcp->scno = subcall + i;
Denys Vlasenkoafc64032011-08-23 13:29:01 +0200574 tcp->u_nargs = sysent[tcp->scno].nargs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000575 break;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000576 case door_style:
577 /*
578 * Oh, yuck. The call code is the *sixth* argument.
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000579 * (don't you mean the *last* argument? - JH)
Wichert Akkerman8829a551999-06-11 13:18:40 +0000580 */
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000581 if (tcp->u_arg[5] < 0 || tcp->u_arg[5] >= nsubcalls)
582 return;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000583 tcp->scno = subcall + tcp->u_arg[5];
Denys Vlasenkoafc64032011-08-23 13:29:01 +0200584 tcp->u_nargs = sysent[tcp->scno].nargs;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000585 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000586 }
587}
588#endif
589
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200590int
591printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000592{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200593 if (entering(tcp)) {
594 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000595
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200596 for (i = 0; i < tcp->u_nargs; i++)
597 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
598 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000599 return 0;
600}
601
Denys Vlasenko72879c62012-02-27 14:18:02 +0100602int
603printargs_lu(struct tcb *tcp)
604{
605 if (entering(tcp)) {
606 int i;
607
608 for (i = 0; i < tcp->u_nargs; i++)
609 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
610 }
611 return 0;
612}
613
614int
615printargs_ld(struct tcb *tcp)
616{
617 if (entering(tcp)) {
618 int i;
619
620 for (i = 0; i < tcp->u_nargs; i++)
621 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
622 }
623 return 0;
624}
625
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200626long
627getrval2(struct tcb *tcp)
628{
629 long val = -1;
630
Denys Vlasenko523635f2012-02-25 02:44:25 +0100631#if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200632 struct pt_regs regs;
633 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
634 return -1;
635 val = regs.u_regs[U_REG_O1];
636#elif defined(SH)
637 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
638 return -1;
639#elif defined(IA64)
640 if (upeek(tcp, PT_R9, &val) < 0)
641 return -1;
642#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200643
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200644 return val;
645}
646
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200647int
648is_restart_error(struct tcb *tcp)
649{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200650 switch (tcp->u_error) {
651 case ERESTARTSYS:
652 case ERESTARTNOINTR:
653 case ERESTARTNOHAND:
654 case ERESTART_RESTARTBLOCK:
655 return 1;
656 default:
657 break;
658 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200659 return 0;
660}
661
Denys Vlasenko523635f2012-02-25 02:44:25 +0100662#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100663struct pt_regs i386_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100664#elif defined(X86_64)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100665/*
666 * On 32 bits, pt_regs and user_regs_struct are the same,
667 * but on 64 bits, user_regs_struct has six more fields:
668 * fs_base, gs_base, ds, es, fs, gs.
669 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
670 */
671static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100672#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200673long r8, r10, psr; /* TODO: make static? */
674long ia32 = 0; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100675#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +0200676static long result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100677#elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200678static long d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100679#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200680static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100681#elif defined(ARM)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200682static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100683#elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200684static long r0;
685static long a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100686#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200687static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100688#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200689static struct pt_regs regs;
690static unsigned long trap;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100691#elif defined(LINUX_MIPSN32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200692static long long a3;
693static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100694#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200695static long a3;
696static long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100697#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200698static long gpr2;
699static long pc;
700static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100701#elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200702static long r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100703#elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200704static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100705#elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200706static long r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100707#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200708static long r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100709#elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200710static long r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100711#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000712
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200713/* Returns:
714 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
715 * 1: ok, continue in trace_syscall().
716 * other: error, trace_syscall() should print error indicator
717 * ("????" etc) and bail out.
718 */
Denys Vlasenko9a36ae52011-08-24 16:47:32 +0200719static
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000720int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200721get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000722{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000723 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000724
Denys Vlasenko523635f2012-02-25 02:44:25 +0100725#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000726 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200727 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000728
729 if (syscall_mode != -ENOSYS) {
730 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000731 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000732 */
733 scno = syscall_mode;
734 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000735 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000736 * Old style of "passing" the scno via the SVC instruction.
737 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000738 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200739 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200740 static const int gpr_offset[16] = {
741 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
742 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
743 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
744 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
745 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000746
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000747 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000748 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000749 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000750 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000751 if (errno) {
752 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000753 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000754 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000755
756 /*
757 * We have to check if the SVC got executed directly or via an
758 * EXECUTE instruction. In case of EXECUTE it is necessary to do
759 * instruction decoding to derive the system call number.
760 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
761 * so that this doesn't work if a SVC opcode is part of an EXECUTE
762 * opcode. Since there is no way to find out the opcode size this
763 * is the best we can do...
764 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000765 if ((opcode & 0xff00) == 0x0a00) {
766 /* SVC opcode */
767 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000768 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000769 else {
770 /* SVC got executed by EXECUTE instruction */
771
772 /*
773 * Do instruction decoding of EXECUTE. If you really want to
774 * understand this, read the Principles of Operations.
775 */
776 svc_addr = (void *) (opcode & 0xfff);
777
778 tmp = 0;
779 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000780 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000781 return -1;
782 svc_addr += tmp;
783
784 tmp = 0;
785 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000786 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000787 return -1;
788 svc_addr += tmp;
789
Denys Vlasenkofb036672009-01-23 16:30:26 +0000790 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000791 if (errno)
792 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100793# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000794 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100795# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000796 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100797# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000798 tmp = 0;
799 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000800 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000801 return -1;
802
803 scno = (scno | tmp) & 0xff;
804 }
805 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100806#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000807 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000808 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100809# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200810 /* TODO: speed up strace by not doing this at every syscall.
811 * We only need to do it after execve.
812 */
813 int currpers;
814 long val;
815 int pid = tcp->pid;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200816
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200817 /* Check for 64/32 bit mode. */
818 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
819 return -1;
820 /* SF is bit 0 of MSR */
821 if (val < 0)
822 currpers = 0;
823 else
824 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000825 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100826# endif
827#elif defined(AVR32)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200828 /* Read complete register set in one go. */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000829 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
830 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200831 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100832#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000833 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000834 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100835#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200836 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000837 return -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200838 scno = i386_regs.orig_eax;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100839#elif defined(X86_64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200840 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200841 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
842 return -1;
843 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +0000844
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200845 /* Check CS register value. On x86-64 linux it is:
846 * 0x33 for long mode (64 bit)
847 * 0x23 for compatibility mode (32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200848 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200849 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200850 case 0x23: currpers = 1; break;
851 case 0x33: currpers = 0; break;
852 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200853 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200854 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200855 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200856 currpers = current_personality;
857 break;
858 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100859# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200860 /* This version analyzes the opcode of a syscall instruction.
861 * (int 0x80 on i386 vs. syscall on x86-64)
862 * It works, but is too complicated.
863 */
864 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +0000865
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200866 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +0000867
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200868 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
869 rip -= 2;
870 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +0000871
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200872 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200873 if (errno)
874 fprintf(stderr, "ptrace_peektext failed: %s\n",
875 strerror(errno));
876 switch (call & 0xffff) {
877 /* x86-64: syscall = 0x0f 0x05 */
878 case 0x050f: currpers = 0; break;
879 /* i386: int 0x80 = 0xcd 0x80 */
880 case 0x80cd: currpers = 1; break;
881 default:
882 currpers = current_personality;
883 fprintf(stderr,
884 "Unknown syscall opcode (0x%04X) while "
885 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200886 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200887 break;
888 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100889# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000890 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100891#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000892# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200893 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000894 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200895 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200896 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200897 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000898 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200899 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000900 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200901 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100902#elif defined(ARM)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200903 /* Read complete register set in one go. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000904 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +0000905 return -1;
906
907 /*
908 * We only need to grab the syscall number on syscall entry.
909 */
910 if (regs.ARM_ip == 0) {
911 /*
912 * Note: we only deal with only 32-bit CPUs here.
913 */
914 if (regs.ARM_cpsr & 0x20) {
915 /*
916 * Get the Thumb-mode system call number
917 */
918 scno = regs.ARM_r7;
919 } else {
920 /*
921 * Get the ARM-mode system call number
922 */
923 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000924 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +0000925 if (errno)
926 return -1;
927
Roland McGrathf691bd22006-04-25 07:34:41 +0000928 /* Handle the EABI syscall convention. We do not
929 bother converting structures between the two
930 ABIs, but basic functionality should work even
931 if strace and the traced program have different
932 ABIs. */
933 if (scno == 0xef000000) {
934 scno = regs.ARM_r7;
935 } else {
936 if ((scno & 0x0ff00000) != 0x0f900000) {
937 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
938 scno);
939 return -1;
940 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000941
Roland McGrathf691bd22006-04-25 07:34:41 +0000942 /*
943 * Fixup the syscall number
944 */
945 scno &= 0x000fffff;
946 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000947 }
Roland McGrath56703312008-05-20 01:35:55 +0000948 if (scno & 0x0f0000) {
949 /*
950 * Handle ARM specific syscall
951 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000952 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +0000953 scno &= 0x0000ffff;
954 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000955 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +0000956
Roland McGrath0f87c492003-06-03 23:29:04 +0000957 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200958 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
959 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000960 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100961#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000962 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000963 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100964#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +0000965 unsigned long long regs[38];
966
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200967 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +0000968 return -1;
969 a3 = regs[REG_A3];
970 r2 = regs[REG_V0];
971
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200972 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200973 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200974 if (a3 == 0 || a3 == -1) {
975 if (debug)
976 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000977 return 0;
978 }
Roland McGrath542c2c62008-05-20 01:11:56 +0000979 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100980#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000981 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000982 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200983 if (upeek(tcp, REG_V0, &scno) < 0)
984 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000985
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200986 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200987 if (a3 == 0 || a3 == -1) {
988 if (debug)
989 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000990 return 0;
991 }
Wichert Akkermanf90da011999-10-31 21:15:38 +0000992 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100993#elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000994 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000995 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200996 if (upeek(tcp, REG_R0, &scno) < 0)
997 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000998
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200999 /*
1000 * Do some sanity checks to figure out if it's
1001 * really a syscall entry
1002 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001003 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001004 if (a3 == 0 || a3 == -1) {
1005 if (debug)
1006 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001007 return 0;
1008 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001009 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001010#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001011 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001012 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001013 return -1;
1014
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001015 /* Disassemble the syscall trap. */
1016 /* Retrieve the syscall trap instruction. */
1017 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001018# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001019 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1020 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001021# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001022 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001023# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001024 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001025 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001026
1027 /* Disassemble the trap to see what personality to use. */
1028 switch (trap) {
1029 case 0x91d02010:
1030 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001031 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001032 break;
1033 case 0x91d0206d:
1034 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001035 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001036 break;
1037 case 0x91d02000:
1038 /* SunOS syscall trap. (pers 1) */
1039 fprintf(stderr, "syscall: SunOS no support\n");
1040 return -1;
1041 case 0x91d02008:
1042 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001043 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001044 break;
1045 case 0x91d02009:
1046 /* NetBSD/FreeBSD syscall trap. */
1047 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1048 return -1;
1049 case 0x91d02027:
1050 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001051 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001052 break;
1053 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001054# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001055 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001056# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001057 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001058# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001059 return -1;
1060 }
1061
1062 /* Extract the system call number from the registers. */
1063 if (trap == 0x91d02027)
1064 scno = 156;
1065 else
1066 scno = regs.u_regs[U_REG_G1];
1067 if (scno == 0) {
1068 scno = regs.u_regs[U_REG_O0];
1069 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1070 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001071#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001072 if (upeek(tcp, PT_GR20, &scno) < 0)
1073 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001074#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001075 /*
1076 * In the new syscall ABI, the system call number is in R3.
1077 */
1078 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1079 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001080
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001081 if (scno < 0) {
1082 /* Odd as it may seem, a glibc bug has been known to cause
1083 glibc to issue bogus negative syscall numbers. So for
1084 our purposes, make strace print what it *should* have been */
1085 long correct_scno = (scno & 0xff);
1086 if (debug)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001087 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001088 "Detected glibc bug: bogus system call"
1089 " number = %ld, correcting to %ld\n",
1090 scno,
1091 correct_scno);
1092 scno = correct_scno;
1093 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001094#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001095 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001096 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001097 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001098#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001099 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1100 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001101#elif defined(TILE)
Chris Metcalfc8c66982009-12-28 10:00:15 -05001102 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1103 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001104#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001105 if (upeek(tcp, 0, &scno) < 0)
1106 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001107#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001108
Denys Vlasenko523635f2012-02-25 02:44:25 +01001109#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001110 /* new syscall ABI returns result in R0 */
1111 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1112 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001113#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001114 /* ABI defines result returned in r9 */
1115 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1116 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001117#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001118
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001119 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001120 return 1;
1121}
1122
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001123/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001124 * Returns:
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001125 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
Roland McGratheb9e2e82009-06-02 16:49:22 -07001126 * 1: ok, continue in trace_syscall().
1127 * other: error, trace_syscall() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001128 * ("????" etc) and bail out.
1129 */
Roland McGratha4d48532005-06-08 20:45:28 +00001130static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001131syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001132{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001133 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001134#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001135 if (i386_regs.eax != -ENOSYS) {
1136 if (debug)
1137 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1138 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001139 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001140#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001141 {
1142 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001143 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001144 rax = (int)rax; /* sign extend from 32 bits */
1145 if (rax != -ENOSYS) {
Denys Vlasenko18beb982011-08-24 16:59:23 +02001146 if (debug)
1147 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1148 return 0;
1149 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001150 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001151#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001152 /* TODO: we already fetched PT_GPR2 in get_scno
1153 * and stored it in syscall_mode, reuse it here
1154 * instead of re-fetching?
1155 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001156 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001157 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001158 if (syscall_mode != -ENOSYS)
1159 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001160 if (gpr2 != syscall_mode) {
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001161 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001162 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001163 return 0;
1164 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001165#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001166 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001167 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001168 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001169 if (d0 != -ENOSYS) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001170 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001171 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001172 return 0;
1173 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001174#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001175 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001176 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001177 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001178 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001179 if (ia32 && r8 != -ENOSYS) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001180 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001181 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001182 return 0;
1183 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001184#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001185 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001186 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001187 if (r10 != -ENOSYS) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001188 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001189 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001190 return 0;
1191 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001192#elif defined(MICROBLAZE)
1193 if (upeek(tcp, 3 * 4, &r3) < 0)
1194 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001195 if (r3 != -ENOSYS) {
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001196 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001197 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001198 return 0;
1199 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001200#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001201 return 1;
1202}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001203
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001204static int
1205internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001206{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001207 /*
1208 * We must always trace a few critical system calls in order to
1209 * correctly support following forks in the presence of tracing
1210 * qualifiers.
1211 */
1212 int (*func)();
1213
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001214 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001215 return 0;
1216
1217 func = sysent[tcp->scno].sys_func;
1218
1219 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001220 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001221 || sys_clone == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001222 )
1223 return internal_fork(tcp);
1224
Denys Vlasenko84703742012-02-25 02:38:52 +01001225#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001226 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001227# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001228 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001229# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001230 )
1231 return internal_exec(tcp);
Roland McGrathc1e45922008-05-27 23:18:29 +00001232#endif
1233
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001234 return 0;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001235}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001236
Roland McGratha4d48532005-06-08 20:45:28 +00001237static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001238syscall_enter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001239{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001240 int i, nargs;
1241
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001242 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001243 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001244 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001245 nargs = tcp->u_nargs = MAX_ARGS;
1246
Denys Vlasenko523635f2012-02-25 02:44:25 +01001247#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001248 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001249 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1250 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001251#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001252 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001253 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1254 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001255#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001256 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001257 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001258 long rbs_end;
1259 /* be backwards compatible with kernel < 2.4.4... */
1260# ifndef PT_RBS_END
1261# define PT_RBS_END PT_AR_BSP
1262# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001263
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001264 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1265 return -1;
1266 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001267 return -1;
1268
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001269 sof = (cfm >> 0) & 0x7f;
1270 sol = (cfm >> 7) & 0x7f;
1271 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1272
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001273 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001274 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1275 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1276 return -1;
1277 }
1278 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001279 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1280 PT_R9 /* ECX = out1 */,
1281 PT_R10 /* EDX = out2 */,
1282 PT_R14 /* ESI = out3 */,
1283 PT_R15 /* EDI = out4 */,
1284 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001285
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001286 for (i = 0; i < nargs; ++i) {
1287 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1288 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001289 /* truncate away IVE sign-extension */
1290 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001291 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001292 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001293#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001294 /* N32 and N64 both use up to six registers. */
1295 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001296
1297 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1298 return -1;
1299
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001300 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001301 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001302# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001303 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001304# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001305 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001306#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001307 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001308 long sp;
1309
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001310 if (upeek(tcp, REG_SP, &sp) < 0)
1311 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001312 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001313 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1314 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001315 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001316 (char *)(tcp->u_arg + 4));
1317 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001318 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001319 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001320 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001321 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001322#elif defined(POWERPC)
1323# ifndef PT_ORIG_R3
1324# define PT_ORIG_R3 34
1325# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001326 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001327 if (upeek(tcp, (i==0) ?
1328 (sizeof(unsigned long) * PT_ORIG_R3) :
1329 ((i+PT_R3) * sizeof(unsigned long)),
1330 &tcp->u_arg[i]) < 0)
1331 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001332 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001333#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001334 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001335 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001336#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001337 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001338 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1339 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001340#elif defined(ARM)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001341 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001342 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001343#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001344 (void)i;
1345 (void)nargs;
1346 tcp->u_arg[0] = regs.r12;
1347 tcp->u_arg[1] = regs.r11;
1348 tcp->u_arg[2] = regs.r10;
1349 tcp->u_arg[3] = regs.r9;
1350 tcp->u_arg[4] = regs.r5;
1351 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001352#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001353 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 +02001354
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001355 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001356 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1357 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001358#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001359 static const int syscall_regs[MAX_ARGS] = {
1360 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1361 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001362 };
1363
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001364 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001365 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001366 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001367#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001368 int i;
1369 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001370 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001371
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001372 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001373 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1374 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001375#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001376 (void)i;
1377 (void)nargs;
1378 if (current_personality == 0) { /* x86-64 ABI */
1379 tcp->u_arg[0] = x86_64_regs.rdi;
1380 tcp->u_arg[1] = x86_64_regs.rsi;
1381 tcp->u_arg[2] = x86_64_regs.rdx;
1382 tcp->u_arg[3] = x86_64_regs.r10;
1383 tcp->u_arg[4] = x86_64_regs.r8;
1384 tcp->u_arg[5] = x86_64_regs.r9;
1385 } else { /* i386 ABI */
1386 /* Sign-extend lower 32 bits */
1387 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1388 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1389 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1390 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1391 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1392 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1393 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001394#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001395 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001396 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1397 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001398#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001399 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001400 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001401 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001402 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001403
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001404 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001405 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1406 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001407#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001408 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001409 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1410 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001411#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001412 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001413 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1414 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001415#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001416 (void)i;
1417 (void)nargs;
1418 tcp->u_arg[0] = i386_regs.ebx;
1419 tcp->u_arg[1] = i386_regs.ecx;
1420 tcp->u_arg[2] = i386_regs.edx;
1421 tcp->u_arg[3] = i386_regs.esi;
1422 tcp->u_arg[4] = i386_regs.edi;
1423 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001424#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001425 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001426 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1427 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001428#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001429 return 1;
1430}
1431
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001432static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001433trace_syscall_entering(struct tcb *tcp)
1434{
1435 int res, scno_good;
1436
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001437#if defined TCB_WAITEXECVE
1438 if (tcp->flags & TCB_WAITEXECVE) {
1439 /* This is the post-execve SIGTRAP. */
1440 tcp->flags &= ~TCB_WAITEXECVE;
1441 return 0;
1442 }
1443#endif
1444
Denys Vlasenko06602d92011-08-24 17:53:52 +02001445 scno_good = res = get_scno(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001446 if (res == 0)
1447 return res;
1448 if (res == 1)
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001449 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001450 if (res == 0)
1451 return res;
1452 if (res == 1)
1453 res = syscall_enter(tcp);
1454 if (res == 0)
1455 return res;
1456
1457 if (res != 1) {
1458 printleader(tcp);
1459 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001460 if (scno_good != 1)
1461 tprintf("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001462 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001463 tprintf("syscall_%lu(", tcp->scno);
1464 else
1465 tprintf("%s(", sysent[tcp->scno].sys_name);
1466 /*
1467 * " <unavailable>" will be added later by the code which
1468 * detects ptrace errors.
1469 */
1470 goto ret;
1471 }
1472
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001473#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1474 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001475# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001476 if (sysent[tcp->scno].sys_func == sys_socketcall) {
1477 decode_subcall(tcp, SYS_socket_subcall,
1478 SYS_socket_nsubcalls, deref_style);
1479 break;
1480 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001481# endif
1482# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001483 if (sysent[tcp->scno].sys_func == sys_ipc) {
1484 decode_subcall(tcp, SYS_ipc_subcall,
1485 SYS_ipc_nsubcalls, shift_style);
1486 break;
1487 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001488# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001489 break;
1490 }
1491#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1492
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001493 internal_syscall(tcp);
1494
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001495 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001496 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1497 (tracing_paths && !pathtrace_match(tcp))) {
1498 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1499 return 0;
1500 }
1501
1502 tcp->flags &= ~TCB_FILTERED;
1503
1504 if (cflag == CFLAG_ONLY_STATS) {
1505 res = 0;
1506 goto ret;
1507 }
1508
1509 printleader(tcp);
1510 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001511 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001512 tprintf("syscall_%lu(", tcp->scno);
1513 else
1514 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001515 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001516 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1517 sysent[tcp->scno].sys_func != sys_exit))
1518 res = printargs(tcp);
1519 else
1520 res = (*sysent[tcp->scno].sys_func)(tcp);
1521
1522 if (fflush(tcp->outf) == EOF)
1523 return -1;
1524 ret:
1525 tcp->flags |= TCB_INSYSCALL;
1526 /* Measure the entrance time as late as possible to avoid errors. */
1527 if (dtime || cflag)
1528 gettimeofday(&tcp->etime, NULL);
1529 return res;
1530}
1531
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001532/* Returns:
1533 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1534 * 1: ok, continue in trace_syscall().
1535 * other: error, trace_syscall() should print error indicator
1536 * ("????" etc) and bail out.
1537 */
1538static int
1539get_syscall_result(struct tcb *tcp)
1540{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001541#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001542 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1543 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001544#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001545# define SO_MASK 0x10000000
1546 {
1547 long flags;
1548 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1549 return -1;
1550 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &result) < 0)
1551 return -1;
1552 if (flags & SO_MASK)
1553 result = -result;
1554 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001555#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001556 /* Read complete register set in one go. */
1557 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1558 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001559#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001560 if (upeek(tcp, PT_R0, &r0) < 0)
1561 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001562#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001563 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001564 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001565#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001566 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001567 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001568#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001569# define IA64_PSR_IS ((long)1 << 34)
1570 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1571 ia32 = (psr & IA64_PSR_IS) != 0;
1572 if (upeek(tcp, PT_R8, &r8) < 0)
1573 return -1;
1574 if (upeek(tcp, PT_R10, &r10) < 0)
1575 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001576#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001577 /* Read complete register set in one go. */
1578 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1579 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001580#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001581 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1582 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001583#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001584 unsigned long long regs[38];
1585
1586 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1587 return -1;
1588 a3 = regs[REG_A3];
1589 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001590#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001591 if (upeek(tcp, REG_A3, &a3) < 0)
1592 return -1;
1593 if (upeek(tcp, REG_V0, &r2) < 0)
1594 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001595#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001596 if (upeek(tcp, REG_A3, &a3) < 0)
1597 return -1;
1598 if (upeek(tcp, REG_R0, &r0) < 0)
1599 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001600#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001601 /* Everything we need is in the current register set. */
1602 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1603 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001604#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001605 if (upeek(tcp, PT_GR28, &r28) < 0)
1606 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001607#elif defined(SH)
1608#elif defined(SH64)
1609#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001610 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1611 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001612#elif defined(TILE)
1613#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001614 if (upeek(tcp, 3 * 4, &r3) < 0)
1615 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001616#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001617
Denys Vlasenko523635f2012-02-25 02:44:25 +01001618#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001619 /* new syscall ABI returns result in R0 */
1620 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1621 return -1;
1622#elif defined(SH64)
1623 /* ABI defines result returned in r9 */
1624 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1625 return -1;
1626#endif
1627
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001628 return 1;
1629}
1630
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001631/* Called at each syscall exit.
1632 * Returns:
1633 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1634 * 1: ok, continue in trace_syscall().
1635 * other: error, trace_syscall() should print error indicator
1636 * ("????" etc) and bail out.
1637 */
1638static int
1639syscall_fixup_on_sysexit(struct tcb *tcp)
1640{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001641#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001642 if (syscall_mode != -ENOSYS)
1643 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001644 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001645 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1646 /*
1647 * Return from execve.
1648 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1649 * flag set for the post-execve SIGTRAP to see and reset.
1650 */
1651 gpr2 = 0;
1652 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001653#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001654 return 1;
1655}
1656
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001657/*
1658 * Check the syscall return value register value for whether it is
1659 * a negated errno code indicating an error, or a success return value.
1660 */
1661static inline int
1662is_negated_errno(unsigned long int val)
1663{
1664 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001665#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001666 if (personality_wordsize[current_personality] < sizeof(val)) {
1667 val = (unsigned int) val;
1668 max = (unsigned int) max;
1669 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001670#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001671 return val > max;
1672}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001673
1674static int
1675get_error(struct tcb *tcp)
1676{
1677 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001678 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001679 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001680 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1681 check_errno = 0;
1682 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001683#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001684 if (check_errno && is_negated_errno(gpr2)) {
1685 tcp->u_rval = -1;
1686 u_error = -gpr2;
1687 }
1688 else {
1689 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001690 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001691#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001692 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001693 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001694 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001695 }
1696 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001697 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001698 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001699#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001700 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001701 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001702 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001703 }
1704 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001705 tcp->u_rval = x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001706 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001707#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001708 if (ia32) {
1709 int err;
1710
1711 err = (int)r8;
1712 if (check_errno && is_negated_errno(err)) {
1713 tcp->u_rval = -1;
1714 u_error = -err;
1715 }
1716 else {
1717 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001718 }
1719 } else {
1720 if (check_errno && r10) {
1721 tcp->u_rval = -1;
1722 u_error = r8;
1723 } else {
1724 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001725 }
1726 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001727#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001728 if (check_errno && a3) {
1729 tcp->u_rval = -1;
1730 u_error = r2;
1731 } else {
1732 tcp->u_rval = r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001733 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001734#elif defined(POWERPC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001735 if (check_errno && is_negated_errno(result)) {
1736 tcp->u_rval = -1;
1737 u_error = -result;
1738 }
1739 else {
1740 tcp->u_rval = result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001741 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001742#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001743 if (check_errno && is_negated_errno(d0)) {
1744 tcp->u_rval = -1;
1745 u_error = -d0;
1746 }
1747 else {
1748 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001749 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001750#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001751 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1752 tcp->u_rval = -1;
1753 u_error = -regs.ARM_r0;
1754 }
1755 else {
1756 tcp->u_rval = regs.ARM_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001757 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001758#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001759 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1760 tcp->u_rval = -1;
1761 u_error = -regs.r12;
1762 }
1763 else {
1764 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001765 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001766#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001767 if (check_errno && is_negated_errno(r0)) {
1768 tcp->u_rval = -1;
1769 u_error = -r0;
1770 } else {
1771 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001772 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001773#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001774 if (check_errno && a3) {
1775 tcp->u_rval = -1;
1776 u_error = r0;
1777 }
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(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001782 if (check_errno && regs.psr & PSR_C) {
1783 tcp->u_rval = -1;
1784 u_error = regs.u_regs[U_REG_O0];
1785 }
1786 else {
1787 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001788 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001789#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001790 if (check_errno && regs.tstate & 0x1100000000UL) {
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(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001798 if (check_errno && is_negated_errno(r28)) {
1799 tcp->u_rval = -1;
1800 u_error = -r28;
1801 }
1802 else {
1803 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001804 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001805#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001806 if (check_errno && is_negated_errno(r0)) {
1807 tcp->u_rval = -1;
1808 u_error = -r0;
1809 }
1810 else {
1811 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001812 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001813#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001814 if (check_errno && is_negated_errno(r9)) {
1815 tcp->u_rval = -1;
1816 u_error = -r9;
1817 }
1818 else {
1819 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001820 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001821#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001822 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1823 tcp->u_rval = -1;
1824 u_error = -r10;
1825 }
1826 else {
1827 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001828 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001829#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001830 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001831 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1832 return -1;
1833 if (check_errno && rval < 0 && rval > -nerrnos) {
1834 tcp->u_rval = -1;
1835 u_error = -rval;
1836 }
1837 else {
1838 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001839 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001840#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001841 if (check_errno && is_negated_errno(r3)) {
1842 tcp->u_rval = -1;
1843 u_error = -r3;
1844 }
1845 else {
1846 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001847 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001848#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001849 tcp->u_error = u_error;
1850 return 1;
1851}
1852
1853static void
1854dumpio(struct tcb *tcp)
1855{
1856 if (syserror(tcp))
1857 return;
1858 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1859 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001860 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001861 return;
1862 if (sysent[tcp->scno].sys_func == printargs)
1863 return;
1864 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1865 if (sysent[tcp->scno].sys_func == sys_read ||
1866 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001867 sysent[tcp->scno].sys_func == sys_recv ||
1868 sysent[tcp->scno].sys_func == sys_recvfrom)
1869 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1870 else if (sysent[tcp->scno].sys_func == sys_readv)
1871 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1872 return;
1873 }
1874 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1875 if (sysent[tcp->scno].sys_func == sys_write ||
1876 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001877 sysent[tcp->scno].sys_func == sys_send ||
1878 sysent[tcp->scno].sys_func == sys_sendto)
1879 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1880 else if (sysent[tcp->scno].sys_func == sys_writev)
1881 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1882 return;
1883 }
1884}
1885
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001886static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001887trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001888{
1889 int sys_res;
1890 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001891 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001892 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001893
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001894 /* Measure the exit time as early as possible to avoid errors. */
1895 if (dtime || cflag)
1896 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001897
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001898#if SUPPORTED_PERSONALITIES > 1
1899 update_personality(tcp, tcp->currpers);
1900#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001901 res = get_syscall_result(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001902 if (res == 0)
1903 return res;
1904 if (res == 1)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001905 res = syscall_fixup_on_sysexit(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001906 if (res == 0)
1907 return res;
1908 if (res == 1)
1909 res = get_error(tcp);
1910 if (res == 0)
1911 return res;
1912 if (res == 1)
1913 internal_syscall(tcp);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001914
Grant Edwards8a082772011-04-07 20:25:40 +00001915 if (res == 1 && filtered(tcp)) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001916 goto ret;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001917 }
1918
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001919 if (tcp->flags & TCB_REPRINT) {
1920 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001921 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001922 tprintf("<... syscall_%lu resumed> ", tcp->scno);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001923 else
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001924 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001925 }
1926
1927 if (cflag) {
1928 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02001929 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02001930 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001931 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001932 }
1933 }
1934
1935 if (res != 1) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001936 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001937 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01001938 tprints("= ? <unavailable>\n");
1939 printing_tcp = NULL;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001940 tcp->flags &= ~TCB_INSYSCALL;
1941 return res;
1942 }
1943
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001944 if (!SCNO_IN_RANGE(tcp->scno)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001945 || (qual_flags[tcp->scno] & QUAL_RAW))
1946 sys_res = printargs(tcp);
1947 else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001948 /* FIXME: not_failing_only (IOW, option -z) is broken:
1949 * failure of syscall is known only after syscall return.
1950 * Thus we end up with something like this on, say, ENOENT:
1951 * open("doesnt_exist", O_RDONLY <unfinished ...>
1952 * {next syscall decode}
1953 * whereas the intended result is that open(...) line
1954 * is not shown at all.
1955 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001956 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02001957 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001958 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
1959 }
1960
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001961 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001962 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02001963 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001964 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001965 qual_flags[tcp->scno] & QUAL_RAW) {
1966 if (u_error)
1967 tprintf("= -1 (errno %ld)", u_error);
1968 else
1969 tprintf("= %#lx", tcp->u_rval);
1970 }
1971 else if (!(sys_res & RVAL_NONE) && u_error) {
1972 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01001973 /* Blocked signals do not interrupt any syscalls.
1974 * In this case syscalls don't return ERESTARTfoo codes.
1975 *
1976 * Deadly signals set to SIG_DFL interrupt syscalls
1977 * and kill the process regardless of which of the codes below
1978 * is returned by the interrupted syscall.
1979 * In some cases, kernel forces a kernel-generated deadly
1980 * signal to be unblocked and set to SIG_DFL (and thus cause
1981 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
1982 * or SIGILL. (The alternative is to leave process spinning
1983 * forever on the faulty instruction - not useful).
1984 *
1985 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
1986 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
1987 * but kernel will always restart them.
1988 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001989 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01001990 /* Most common type of signal-interrupted syscall exit code.
1991 * The system call will be restarted with the same arguments
1992 * if SA_RESTART is set; otherwise, it will fail with EINTR.
1993 */
1994 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001995 break;
1996 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01001997 /* Rare. For example, fork() returns this if interrupted.
1998 * SA_RESTART is ignored (assumed set): the restart is unconditional.
1999 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002000 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002001 break;
2002 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002003 /* pause(), rt_sigsuspend() etc use this code.
2004 * SA_RESTART is ignored (assumed not set):
2005 * syscall won't restart (will return EINTR instead)
2006 * even after signal with SA_RESTART set.
2007 * However, after SIG_IGN or SIG_DFL signal it will.
2008 */
2009 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002010 break;
2011 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002012 /* Syscalls like nanosleep(), poll() which can't be
2013 * restarted with their original arguments use this
2014 * code. Kernel will execute restart_syscall() instead,
2015 * which changes arguments before restarting syscall.
2016 * SA_RESTART is ignored (assumed not set) similarly
2017 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2018 * since restart data is saved in "restart block"
2019 * in task struct, and if signal handler uses a syscall
2020 * which in turn saves another such restart block,
2021 * old data is lost and restart becomes impossible)
2022 */
2023 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002024 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002025 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002026 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002027 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002028 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002029 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002030 strerror(u_error));
2031 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002032 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002033 strerror(u_error));
2034 break;
2035 }
2036 if ((sys_res & RVAL_STR) && tcp->auxstr)
2037 tprintf(" (%s)", tcp->auxstr);
2038 }
2039 else {
2040 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002041 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002042 else {
2043 switch (sys_res & RVAL_MASK) {
2044 case RVAL_HEX:
2045 tprintf("= %#lx", tcp->u_rval);
2046 break;
2047 case RVAL_OCTAL:
2048 tprintf("= %#lo", tcp->u_rval);
2049 break;
2050 case RVAL_UDECIMAL:
2051 tprintf("= %lu", tcp->u_rval);
2052 break;
2053 case RVAL_DECIMAL:
2054 tprintf("= %ld", tcp->u_rval);
2055 break;
2056#ifdef HAVE_LONG_LONG
2057 case RVAL_LHEX:
2058 tprintf("= %#llx", tcp->u_lrval);
2059 break;
2060 case RVAL_LOCTAL:
2061 tprintf("= %#llo", tcp->u_lrval);
2062 break;
2063 case RVAL_LUDECIMAL:
2064 tprintf("= %llu", tcp->u_lrval);
2065 break;
2066 case RVAL_LDECIMAL:
2067 tprintf("= %lld", tcp->u_lrval);
2068 break;
2069#endif
2070 default:
2071 fprintf(stderr,
2072 "invalid rval format\n");
2073 break;
2074 }
2075 }
2076 if ((sys_res & RVAL_STR) && tcp->auxstr)
2077 tprintf(" (%s)", tcp->auxstr);
2078 }
2079 if (dtime) {
2080 tv_sub(&tv, &tv, &tcp->etime);
2081 tprintf(" <%ld.%06ld>",
2082 (long) tv.tv_sec, (long) tv.tv_usec);
2083 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002084 tprints("\n");
2085 printing_tcp = NULL;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002086
2087 dumpio(tcp);
2088 if (fflush(tcp->outf) == EOF)
2089 return -1;
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}