blob: 191127b04be19c417500b0be85129c26a427adad [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)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100513 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000514 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000515 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000516 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000517 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000518 return;
519}
520
Wichert Akkerman8829a551999-06-11 13:18:40 +0000521enum subcall_style { shift_style, deref_style, mask_style, door_style };
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000522
Denys Vlasenko84703742012-02-25 02:38:52 +0100523#if !(defined(ALPHA) || defined(MIPS) || defined(__ARM_EABI__))
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000524
Roland McGratha4d48532005-06-08 20:45:28 +0000525static void
Denys Vlasenko12014262011-05-30 14:00:14 +0200526decode_subcall(struct tcb *tcp, int subcall, int nsubcalls, enum subcall_style style)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000527{
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000528 unsigned long addr, mask;
Denys Vlasenko4b887a52011-08-23 13:32:38 +0200529 int i, n;
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000530 int size = personality_wordsize[current_personality];
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000531
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000532 switch (style) {
533 case shift_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000534 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
535 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000536 tcp->scno = subcall + tcp->u_arg[0];
Denys Vlasenko4b887a52011-08-23 13:32:38 +0200537 tcp->u_nargs = n = sysent[tcp->scno].nargs;
538 for (i = 0; i < n; i++)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000539 tcp->u_arg[i] = tcp->u_arg[i + 1];
540 break;
541 case deref_style:
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000542 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
543 return;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000544 tcp->scno = subcall + tcp->u_arg[0];
545 addr = tcp->u_arg[1];
Denys Vlasenko4b887a52011-08-23 13:32:38 +0200546 tcp->u_nargs = n = sysent[tcp->scno].nargs;
547 for (i = 0; i < n; i++) {
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000548 if (size == sizeof(int)) {
549 unsigned int arg;
550 if (umove(tcp, addr, &arg) < 0)
551 arg = 0;
552 tcp->u_arg[i] = arg;
553 }
554 else if (size == sizeof(long)) {
555 unsigned long arg;
556 if (umove(tcp, addr, &arg) < 0)
557 arg = 0;
558 tcp->u_arg[i] = arg;
559 }
560 else
561 abort();
562 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000563 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000564 break;
565 case mask_style:
566 mask = (tcp->u_arg[0] >> 8) & 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000567 for (i = 0; mask; i++)
568 mask >>= 1;
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000569 if (i >= nsubcalls)
570 return;
571 tcp->u_arg[0] &= 0xff;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000572 tcp->scno = subcall + i;
Denys Vlasenkoafc64032011-08-23 13:29:01 +0200573 tcp->u_nargs = sysent[tcp->scno].nargs;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000574 break;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000575 case door_style:
576 /*
577 * Oh, yuck. The call code is the *sixth* argument.
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000578 * (don't you mean the *last* argument? - JH)
Wichert Akkerman8829a551999-06-11 13:18:40 +0000579 */
Wichert Akkerman16a03d22000-08-10 02:14:04 +0000580 if (tcp->u_arg[5] < 0 || tcp->u_arg[5] >= nsubcalls)
581 return;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000582 tcp->scno = subcall + tcp->u_arg[5];
Denys Vlasenkoafc64032011-08-23 13:29:01 +0200583 tcp->u_nargs = sysent[tcp->scno].nargs;
Wichert Akkerman8829a551999-06-11 13:18:40 +0000584 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000585 }
586}
587#endif
588
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200589int
590printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000591{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200592 if (entering(tcp)) {
593 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000594
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200595 for (i = 0; i < tcp->u_nargs; i++)
596 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
597 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000598 return 0;
599}
600
Denys Vlasenko72879c62012-02-27 14:18:02 +0100601int
602printargs_lu(struct tcb *tcp)
603{
604 if (entering(tcp)) {
605 int i;
606
607 for (i = 0; i < tcp->u_nargs; i++)
608 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
609 }
610 return 0;
611}
612
613int
614printargs_ld(struct tcb *tcp)
615{
616 if (entering(tcp)) {
617 int i;
618
619 for (i = 0; i < tcp->u_nargs; i++)
620 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
621 }
622 return 0;
623}
624
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200625long
626getrval2(struct tcb *tcp)
627{
628 long val = -1;
629
Denys Vlasenko523635f2012-02-25 02:44:25 +0100630#if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200631 struct pt_regs regs;
632 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
633 return -1;
634 val = regs.u_regs[U_REG_O1];
635#elif defined(SH)
636 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
637 return -1;
638#elif defined(IA64)
639 if (upeek(tcp, PT_R9, &val) < 0)
640 return -1;
641#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200642
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200643 return val;
644}
645
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200646int
647is_restart_error(struct tcb *tcp)
648{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200649 switch (tcp->u_error) {
650 case ERESTARTSYS:
651 case ERESTARTNOINTR:
652 case ERESTARTNOHAND:
653 case ERESTART_RESTARTBLOCK:
654 return 1;
655 default:
656 break;
657 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200658 return 0;
659}
660
Denys Vlasenko523635f2012-02-25 02:44:25 +0100661#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100662struct pt_regs i386_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100663#elif defined(X86_64)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100664/*
665 * On 32 bits, pt_regs and user_regs_struct are the same,
666 * but on 64 bits, user_regs_struct has six more fields:
667 * fs_base, gs_base, ds, es, fs, gs.
668 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
669 */
670static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100671#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200672long r8, r10, psr; /* TODO: make static? */
673long ia32 = 0; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100674#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +0200675static long result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100676#elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200677static long d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100678#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200679static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100680#elif defined(ARM)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200681static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100682#elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200683static long r0;
684static long a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100685#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200686static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100687#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200688static struct pt_regs regs;
689static unsigned long trap;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100690#elif defined(LINUX_MIPSN32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200691static long long a3;
692static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100693#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200694static long a3;
695static long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100696#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200697static long gpr2;
698static long pc;
699static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100700#elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200701static long r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100702#elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200703static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100704#elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200705static long r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100706#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200707static long r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100708#elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200709static long r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100710#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000711
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200712/* Returns:
713 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
714 * 1: ok, continue in trace_syscall().
715 * other: error, trace_syscall() should print error indicator
716 * ("????" etc) and bail out.
717 */
Denys Vlasenko9a36ae52011-08-24 16:47:32 +0200718static
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000719int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200720get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000721{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000722 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000723
Denys Vlasenko523635f2012-02-25 02:44:25 +0100724#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000725 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200726 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000727
728 if (syscall_mode != -ENOSYS) {
729 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000730 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000731 */
732 scno = syscall_mode;
733 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000734 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000735 * Old style of "passing" the scno via the SVC instruction.
736 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000737 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200738 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200739 static const int gpr_offset[16] = {
740 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
741 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
742 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
743 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
744 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000745
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000746 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000747 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000748 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000749 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000750 if (errno) {
751 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000752 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000753 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000754
755 /*
756 * We have to check if the SVC got executed directly or via an
757 * EXECUTE instruction. In case of EXECUTE it is necessary to do
758 * instruction decoding to derive the system call number.
759 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
760 * so that this doesn't work if a SVC opcode is part of an EXECUTE
761 * opcode. Since there is no way to find out the opcode size this
762 * is the best we can do...
763 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000764 if ((opcode & 0xff00) == 0x0a00) {
765 /* SVC opcode */
766 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000767 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000768 else {
769 /* SVC got executed by EXECUTE instruction */
770
771 /*
772 * Do instruction decoding of EXECUTE. If you really want to
773 * understand this, read the Principles of Operations.
774 */
775 svc_addr = (void *) (opcode & 0xfff);
776
777 tmp = 0;
778 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000779 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000780 return -1;
781 svc_addr += tmp;
782
783 tmp = 0;
784 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000785 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000786 return -1;
787 svc_addr += tmp;
788
Denys Vlasenkofb036672009-01-23 16:30:26 +0000789 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000790 if (errno)
791 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100792# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000793 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100794# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000795 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100796# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000797 tmp = 0;
798 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000799 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000800 return -1;
801
802 scno = (scno | tmp) & 0xff;
803 }
804 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100805#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000806 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000807 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100808# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200809 /* TODO: speed up strace by not doing this at every syscall.
810 * We only need to do it after execve.
811 */
812 int currpers;
813 long val;
814 int pid = tcp->pid;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200815
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200816 /* Check for 64/32 bit mode. */
817 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
818 return -1;
819 /* SF is bit 0 of MSR */
820 if (val < 0)
821 currpers = 0;
822 else
823 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000824 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100825# endif
826#elif defined(AVR32)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200827 /* Read complete register set in one go. */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000828 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
829 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200830 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100831#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000832 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000833 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100834#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200835 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000836 return -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200837 scno = i386_regs.orig_eax;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100838#elif defined(X86_64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200839 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200840 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
841 return -1;
842 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +0000843
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200844 /* Check CS register value. On x86-64 linux it is:
845 * 0x33 for long mode (64 bit)
846 * 0x23 for compatibility mode (32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200847 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200848 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200849 case 0x23: currpers = 1; break;
850 case 0x33: currpers = 0; break;
851 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200852 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200853 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200854 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200855 currpers = current_personality;
856 break;
857 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100858# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200859 /* This version analyzes the opcode of a syscall instruction.
860 * (int 0x80 on i386 vs. syscall on x86-64)
861 * It works, but is too complicated.
862 */
863 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +0000864
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200865 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +0000866
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200867 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
868 rip -= 2;
869 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +0000870
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200871 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200872 if (errno)
873 fprintf(stderr, "ptrace_peektext failed: %s\n",
874 strerror(errno));
875 switch (call & 0xffff) {
876 /* x86-64: syscall = 0x0f 0x05 */
877 case 0x050f: currpers = 0; break;
878 /* i386: int 0x80 = 0xcd 0x80 */
879 case 0x80cd: currpers = 1; break;
880 default:
881 currpers = current_personality;
882 fprintf(stderr,
883 "Unknown syscall opcode (0x%04X) while "
884 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200885 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200886 break;
887 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100888# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000889 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100890#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000891# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200892 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000893 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200894 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200895 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200896 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000897 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200898 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000899 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200900 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100901#elif defined(ARM)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200902 /* Read complete register set in one go. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000903 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +0000904 return -1;
905
906 /*
907 * We only need to grab the syscall number on syscall entry.
908 */
909 if (regs.ARM_ip == 0) {
910 /*
911 * Note: we only deal with only 32-bit CPUs here.
912 */
913 if (regs.ARM_cpsr & 0x20) {
914 /*
915 * Get the Thumb-mode system call number
916 */
917 scno = regs.ARM_r7;
918 } else {
919 /*
920 * Get the ARM-mode system call number
921 */
922 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000923 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +0000924 if (errno)
925 return -1;
926
Roland McGrathf691bd22006-04-25 07:34:41 +0000927 /* Handle the EABI syscall convention. We do not
928 bother converting structures between the two
929 ABIs, but basic functionality should work even
930 if strace and the traced program have different
931 ABIs. */
932 if (scno == 0xef000000) {
933 scno = regs.ARM_r7;
934 } else {
935 if ((scno & 0x0ff00000) != 0x0f900000) {
936 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
937 scno);
938 return -1;
939 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000940
Roland McGrathf691bd22006-04-25 07:34:41 +0000941 /*
942 * Fixup the syscall number
943 */
944 scno &= 0x000fffff;
945 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000946 }
Roland McGrath56703312008-05-20 01:35:55 +0000947 if (scno & 0x0f0000) {
948 /*
949 * Handle ARM specific syscall
950 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000951 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +0000952 scno &= 0x0000ffff;
953 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000954 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +0000955
Roland McGrath0f87c492003-06-03 23:29:04 +0000956 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200957 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
958 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000959 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100960#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000961 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000962 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100963#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +0000964 unsigned long long regs[38];
965
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200966 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +0000967 return -1;
968 a3 = regs[REG_A3];
969 r2 = regs[REG_V0];
970
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200971 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200972 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200973 if (a3 == 0 || a3 == -1) {
974 if (debug)
975 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000976 return 0;
977 }
Roland McGrath542c2c62008-05-20 01:11:56 +0000978 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100979#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000980 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000981 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200982 if (upeek(tcp, REG_V0, &scno) < 0)
983 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000984
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200985 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200986 if (a3 == 0 || a3 == -1) {
987 if (debug)
988 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000989 return 0;
990 }
Wichert Akkermanf90da011999-10-31 21:15:38 +0000991 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100992#elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000993 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000994 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200995 if (upeek(tcp, REG_R0, &scno) < 0)
996 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000997
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200998 /*
999 * Do some sanity checks to figure out if it's
1000 * really a syscall entry
1001 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001002 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001003 if (a3 == 0 || a3 == -1) {
1004 if (debug)
1005 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001006 return 0;
1007 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001008 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001009#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001010 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +00001011 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001012 return -1;
1013
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001014 /* Disassemble the syscall trap. */
1015 /* Retrieve the syscall trap instruction. */
1016 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001017# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001018 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1019 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001020# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001021 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001022# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001023 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001024 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001025
1026 /* Disassemble the trap to see what personality to use. */
1027 switch (trap) {
1028 case 0x91d02010:
1029 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001030 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001031 break;
1032 case 0x91d0206d:
1033 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001034 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001035 break;
1036 case 0x91d02000:
1037 /* SunOS syscall trap. (pers 1) */
1038 fprintf(stderr, "syscall: SunOS no support\n");
1039 return -1;
1040 case 0x91d02008:
1041 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001042 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001043 break;
1044 case 0x91d02009:
1045 /* NetBSD/FreeBSD syscall trap. */
1046 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1047 return -1;
1048 case 0x91d02027:
1049 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001050 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001051 break;
1052 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001053# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001054 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001055# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001056 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001057# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001058 return -1;
1059 }
1060
1061 /* Extract the system call number from the registers. */
1062 if (trap == 0x91d02027)
1063 scno = 156;
1064 else
1065 scno = regs.u_regs[U_REG_G1];
1066 if (scno == 0) {
1067 scno = regs.u_regs[U_REG_O0];
1068 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1069 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001070#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001071 if (upeek(tcp, PT_GR20, &scno) < 0)
1072 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001073#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001074 /*
1075 * In the new syscall ABI, the system call number is in R3.
1076 */
1077 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1078 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001079
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001080 if (scno < 0) {
1081 /* Odd as it may seem, a glibc bug has been known to cause
1082 glibc to issue bogus negative syscall numbers. So for
1083 our purposes, make strace print what it *should* have been */
1084 long correct_scno = (scno & 0xff);
1085 if (debug)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001086 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001087 "Detected glibc bug: bogus system call"
1088 " number = %ld, correcting to %ld\n",
1089 scno,
1090 correct_scno);
1091 scno = correct_scno;
1092 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001093#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001094 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001095 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001096 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001097#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001098 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1099 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001100#elif defined(TILE)
Chris Metcalfc8c66982009-12-28 10:00:15 -05001101 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1102 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001103#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001104 if (upeek(tcp, 0, &scno) < 0)
1105 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001106#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001107
Denys Vlasenko523635f2012-02-25 02:44:25 +01001108#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001109 /* new syscall ABI returns result in R0 */
1110 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1111 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001112#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001113 /* ABI defines result returned in r9 */
1114 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1115 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001116#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001117
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001118 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001119 return 1;
1120}
1121
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001122/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001123 * Returns:
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001124 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
Roland McGratheb9e2e82009-06-02 16:49:22 -07001125 * 1: ok, continue in trace_syscall().
1126 * other: error, trace_syscall() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001127 * ("????" etc) and bail out.
1128 */
Roland McGratha4d48532005-06-08 20:45:28 +00001129static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001130syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001131{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001132 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001133#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001134 if (i386_regs.eax != -ENOSYS) {
1135 if (debug)
1136 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1137 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001138 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001139#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001140 {
1141 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001142 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001143 rax = (int)rax; /* sign extend from 32 bits */
1144 if (rax != -ENOSYS) {
Denys Vlasenko18beb982011-08-24 16:59:23 +02001145 if (debug)
1146 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1147 return 0;
1148 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001149 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001150#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001151 /* TODO: we already fetched PT_GPR2 in get_scno
1152 * and stored it in syscall_mode, reuse it here
1153 * instead of re-fetching?
1154 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001155 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001156 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001157 if (syscall_mode != -ENOSYS)
1158 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001159 if (gpr2 != syscall_mode) {
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001160 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001161 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001162 return 0;
1163 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001164#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001165 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001166 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001167 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001168 if (d0 != -ENOSYS) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001169 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001170 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001171 return 0;
1172 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001173#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001174 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001175 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001176 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001177 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001178 if (ia32 && r8 != -ENOSYS) {
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001179 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001180 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001181 return 0;
1182 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001183#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001184 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001185 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001186 if (r10 != -ENOSYS) {
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001187 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001188 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001189 return 0;
1190 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001191#elif defined(MICROBLAZE)
1192 if (upeek(tcp, 3 * 4, &r3) < 0)
1193 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001194 if (r3 != -ENOSYS) {
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001195 if (debug)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001196 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001197 return 0;
1198 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001199#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001200 return 1;
1201}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001202
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001203static int
1204internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001205{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001206 /*
1207 * We must always trace a few critical system calls in order to
1208 * correctly support following forks in the presence of tracing
1209 * qualifiers.
1210 */
1211 int (*func)();
1212
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001213 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001214 return 0;
1215
1216 func = sysent[tcp->scno].sys_func;
1217
1218 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001219 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001220 || sys_clone == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001221 )
1222 return internal_fork(tcp);
1223
Denys Vlasenko84703742012-02-25 02:38:52 +01001224#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001225 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001226# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001227 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001228# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001229 )
1230 return internal_exec(tcp);
Roland McGrathc1e45922008-05-27 23:18:29 +00001231#endif
1232
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001233 return 0;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001234}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001235
Roland McGratha4d48532005-06-08 20:45:28 +00001236static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001237syscall_enter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001238{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001239 int i, nargs;
1240
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001241 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001242 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001243 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001244 nargs = tcp->u_nargs = MAX_ARGS;
1245
Denys Vlasenko523635f2012-02-25 02:44:25 +01001246#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001247 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001248 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1249 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001250#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001251 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001252 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1253 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001254#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001255 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001256 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001257 long rbs_end;
1258 /* be backwards compatible with kernel < 2.4.4... */
1259# ifndef PT_RBS_END
1260# define PT_RBS_END PT_AR_BSP
1261# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001262
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001263 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1264 return -1;
1265 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001266 return -1;
1267
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001268 sof = (cfm >> 0) & 0x7f;
1269 sol = (cfm >> 7) & 0x7f;
1270 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1271
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001272 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001273 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1274 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1275 return -1;
1276 }
1277 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001278 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1279 PT_R9 /* ECX = out1 */,
1280 PT_R10 /* EDX = out2 */,
1281 PT_R14 /* ESI = out3 */,
1282 PT_R15 /* EDI = out4 */,
1283 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001284
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001285 for (i = 0; i < nargs; ++i) {
1286 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1287 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001288 /* truncate away IVE sign-extension */
1289 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001290 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001291 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001292#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001293 /* N32 and N64 both use up to six registers. */
1294 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001295
1296 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1297 return -1;
1298
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001299 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001300 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001301# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001302 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001303# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001304 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001305#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001306 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001307 long sp;
1308
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001309 if (upeek(tcp, REG_SP, &sp) < 0)
1310 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001311 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001312 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1313 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001314 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001315 (char *)(tcp->u_arg + 4));
1316 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001317 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001318 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001319 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001320 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001321#elif defined(POWERPC)
1322# ifndef PT_ORIG_R3
1323# define PT_ORIG_R3 34
1324# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001325 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001326 if (upeek(tcp, (i==0) ?
1327 (sizeof(unsigned long) * PT_ORIG_R3) :
1328 ((i+PT_R3) * sizeof(unsigned long)),
1329 &tcp->u_arg[i]) < 0)
1330 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001331 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001332#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001333 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001334 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001335#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001336 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001337 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1338 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001339#elif defined(ARM)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001340 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001341 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001342#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001343 (void)i;
1344 (void)nargs;
1345 tcp->u_arg[0] = regs.r12;
1346 tcp->u_arg[1] = regs.r11;
1347 tcp->u_arg[2] = regs.r10;
1348 tcp->u_arg[3] = regs.r9;
1349 tcp->u_arg[4] = regs.r5;
1350 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001351#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001352 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 +02001353
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001354 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001355 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1356 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001357#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001358 static const int syscall_regs[MAX_ARGS] = {
1359 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1360 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001361 };
1362
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001363 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001364 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001365 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001366#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001367 int i;
1368 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001369 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001370
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001371 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001372 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1373 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001374#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001375 (void)i;
1376 (void)nargs;
1377 if (current_personality == 0) { /* x86-64 ABI */
1378 tcp->u_arg[0] = x86_64_regs.rdi;
1379 tcp->u_arg[1] = x86_64_regs.rsi;
1380 tcp->u_arg[2] = x86_64_regs.rdx;
1381 tcp->u_arg[3] = x86_64_regs.r10;
1382 tcp->u_arg[4] = x86_64_regs.r8;
1383 tcp->u_arg[5] = x86_64_regs.r9;
1384 } else { /* i386 ABI */
1385 /* Sign-extend lower 32 bits */
1386 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1387 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1388 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1389 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1390 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1391 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1392 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001393#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001394 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001395 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1396 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001397#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001398 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001399 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001400 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001401 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001402
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001403 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001404 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1405 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001406#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001407 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001408 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1409 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001410#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001411 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001412 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1413 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001414#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001415 (void)i;
1416 (void)nargs;
1417 tcp->u_arg[0] = i386_regs.ebx;
1418 tcp->u_arg[1] = i386_regs.ecx;
1419 tcp->u_arg[2] = i386_regs.edx;
1420 tcp->u_arg[3] = i386_regs.esi;
1421 tcp->u_arg[4] = i386_regs.edi;
1422 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001423#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001424 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001425 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1426 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001427#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001428 return 1;
1429}
1430
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001431static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001432trace_syscall_entering(struct tcb *tcp)
1433{
1434 int res, scno_good;
1435
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001436#if defined TCB_WAITEXECVE
1437 if (tcp->flags & TCB_WAITEXECVE) {
1438 /* This is the post-execve SIGTRAP. */
1439 tcp->flags &= ~TCB_WAITEXECVE;
1440 return 0;
1441 }
1442#endif
1443
Denys Vlasenko06602d92011-08-24 17:53:52 +02001444 scno_good = res = get_scno(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001445 if (res == 0)
1446 return res;
1447 if (res == 1)
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001448 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001449 if (res == 0)
1450 return res;
1451 if (res == 1)
1452 res = syscall_enter(tcp);
1453 if (res == 0)
1454 return res;
1455
1456 if (res != 1) {
1457 printleader(tcp);
1458 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001459 if (scno_good != 1)
1460 tprintf("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001461 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001462 tprintf("syscall_%lu(", tcp->scno);
1463 else
1464 tprintf("%s(", sysent[tcp->scno].sys_name);
1465 /*
1466 * " <unavailable>" will be added later by the code which
1467 * detects ptrace errors.
1468 */
1469 goto ret;
1470 }
1471
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001472#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1473 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001474# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001475 if (sysent[tcp->scno].sys_func == sys_socketcall) {
1476 decode_subcall(tcp, SYS_socket_subcall,
1477 SYS_socket_nsubcalls, deref_style);
1478 break;
1479 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001480# endif
1481# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001482 if (sysent[tcp->scno].sys_func == sys_ipc) {
1483 decode_subcall(tcp, SYS_ipc_subcall,
1484 SYS_ipc_nsubcalls, shift_style);
1485 break;
1486 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001487# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001488 break;
1489 }
1490#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1491
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001492 internal_syscall(tcp);
1493
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001494 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001495 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1496 (tracing_paths && !pathtrace_match(tcp))) {
1497 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1498 return 0;
1499 }
1500
1501 tcp->flags &= ~TCB_FILTERED;
1502
1503 if (cflag == CFLAG_ONLY_STATS) {
1504 res = 0;
1505 goto ret;
1506 }
1507
1508 printleader(tcp);
1509 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001510 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001511 tprintf("syscall_%lu(", tcp->scno);
1512 else
1513 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001514 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001515 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1516 sysent[tcp->scno].sys_func != sys_exit))
1517 res = printargs(tcp);
1518 else
1519 res = (*sysent[tcp->scno].sys_func)(tcp);
1520
1521 if (fflush(tcp->outf) == EOF)
1522 return -1;
1523 ret:
1524 tcp->flags |= TCB_INSYSCALL;
1525 /* Measure the entrance time as late as possible to avoid errors. */
1526 if (dtime || cflag)
1527 gettimeofday(&tcp->etime, NULL);
1528 return res;
1529}
1530
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001531/* Returns:
1532 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1533 * 1: ok, continue in trace_syscall().
1534 * other: error, trace_syscall() should print error indicator
1535 * ("????" etc) and bail out.
1536 */
1537static int
1538get_syscall_result(struct tcb *tcp)
1539{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001540#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001541 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1542 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001543#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001544# define SO_MASK 0x10000000
1545 {
1546 long flags;
1547 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1548 return -1;
1549 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &result) < 0)
1550 return -1;
1551 if (flags & SO_MASK)
1552 result = -result;
1553 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001554#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001555 /* Read complete register set in one go. */
1556 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1557 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001558#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001559 if (upeek(tcp, PT_R0, &r0) < 0)
1560 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001561#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001562 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001563 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001564#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001565 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001566 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001567#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001568# define IA64_PSR_IS ((long)1 << 34)
1569 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1570 ia32 = (psr & IA64_PSR_IS) != 0;
1571 if (upeek(tcp, PT_R8, &r8) < 0)
1572 return -1;
1573 if (upeek(tcp, PT_R10, &r10) < 0)
1574 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001575#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001576 /* Read complete register set in one go. */
1577 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1578 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001579#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001580 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1581 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001582#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001583 unsigned long long regs[38];
1584
1585 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1586 return -1;
1587 a3 = regs[REG_A3];
1588 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001589#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001590 if (upeek(tcp, REG_A3, &a3) < 0)
1591 return -1;
1592 if (upeek(tcp, REG_V0, &r2) < 0)
1593 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001594#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001595 if (upeek(tcp, REG_A3, &a3) < 0)
1596 return -1;
1597 if (upeek(tcp, REG_R0, &r0) < 0)
1598 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001599#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001600 /* Everything we need is in the current register set. */
1601 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1602 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001603#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001604 if (upeek(tcp, PT_GR28, &r28) < 0)
1605 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001606#elif defined(SH)
1607#elif defined(SH64)
1608#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001609 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1610 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001611#elif defined(TILE)
1612#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001613 if (upeek(tcp, 3 * 4, &r3) < 0)
1614 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001615#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001616
Denys Vlasenko523635f2012-02-25 02:44:25 +01001617#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001618 /* new syscall ABI returns result in R0 */
1619 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1620 return -1;
1621#elif defined(SH64)
1622 /* ABI defines result returned in r9 */
1623 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1624 return -1;
1625#endif
1626
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001627 return 1;
1628}
1629
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001630/* Called at each syscall exit.
1631 * Returns:
1632 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1633 * 1: ok, continue in trace_syscall().
1634 * other: error, trace_syscall() should print error indicator
1635 * ("????" etc) and bail out.
1636 */
1637static int
1638syscall_fixup_on_sysexit(struct tcb *tcp)
1639{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001640#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001641 if (syscall_mode != -ENOSYS)
1642 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001643 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001644 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1645 /*
1646 * Return from execve.
1647 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1648 * flag set for the post-execve SIGTRAP to see and reset.
1649 */
1650 gpr2 = 0;
1651 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001652#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001653 return 1;
1654}
1655
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001656/*
1657 * Check the syscall return value register value for whether it is
1658 * a negated errno code indicating an error, or a success return value.
1659 */
1660static inline int
1661is_negated_errno(unsigned long int val)
1662{
1663 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001664#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001665 if (personality_wordsize[current_personality] < sizeof(val)) {
1666 val = (unsigned int) val;
1667 max = (unsigned int) max;
1668 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001669#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001670 return val > max;
1671}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001672
1673static int
1674get_error(struct tcb *tcp)
1675{
1676 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001677 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001678 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001679 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1680 check_errno = 0;
1681 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001682#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001683 if (check_errno && is_negated_errno(gpr2)) {
1684 tcp->u_rval = -1;
1685 u_error = -gpr2;
1686 }
1687 else {
1688 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001689 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001690#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001691 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001692 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001693 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001694 }
1695 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001696 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001697 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001698#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001699 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001700 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001701 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001702 }
1703 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001704 tcp->u_rval = x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001705 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001706#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001707 if (ia32) {
1708 int err;
1709
1710 err = (int)r8;
1711 if (check_errno && is_negated_errno(err)) {
1712 tcp->u_rval = -1;
1713 u_error = -err;
1714 }
1715 else {
1716 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001717 }
1718 } else {
1719 if (check_errno && r10) {
1720 tcp->u_rval = -1;
1721 u_error = r8;
1722 } else {
1723 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001724 }
1725 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001726#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001727 if (check_errno && a3) {
1728 tcp->u_rval = -1;
1729 u_error = r2;
1730 } else {
1731 tcp->u_rval = r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001732 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001733#elif defined(POWERPC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001734 if (check_errno && is_negated_errno(result)) {
1735 tcp->u_rval = -1;
1736 u_error = -result;
1737 }
1738 else {
1739 tcp->u_rval = result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001740 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001741#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001742 if (check_errno && is_negated_errno(d0)) {
1743 tcp->u_rval = -1;
1744 u_error = -d0;
1745 }
1746 else {
1747 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001748 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001749#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001750 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1751 tcp->u_rval = -1;
1752 u_error = -regs.ARM_r0;
1753 }
1754 else {
1755 tcp->u_rval = regs.ARM_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001756 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001757#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001758 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1759 tcp->u_rval = -1;
1760 u_error = -regs.r12;
1761 }
1762 else {
1763 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001764 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001765#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001766 if (check_errno && is_negated_errno(r0)) {
1767 tcp->u_rval = -1;
1768 u_error = -r0;
1769 } else {
1770 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001771 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001772#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001773 if (check_errno && a3) {
1774 tcp->u_rval = -1;
1775 u_error = r0;
1776 }
1777 else {
1778 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001779 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001780#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001781 if (check_errno && regs.psr & PSR_C) {
1782 tcp->u_rval = -1;
1783 u_error = regs.u_regs[U_REG_O0];
1784 }
1785 else {
1786 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001787 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001788#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001789 if (check_errno && regs.tstate & 0x1100000000UL) {
1790 tcp->u_rval = -1;
1791 u_error = regs.u_regs[U_REG_O0];
1792 }
1793 else {
1794 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001795 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001796#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001797 if (check_errno && is_negated_errno(r28)) {
1798 tcp->u_rval = -1;
1799 u_error = -r28;
1800 }
1801 else {
1802 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001803 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001804#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001805 if (check_errno && is_negated_errno(r0)) {
1806 tcp->u_rval = -1;
1807 u_error = -r0;
1808 }
1809 else {
1810 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001811 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001812#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001813 if (check_errno && is_negated_errno(r9)) {
1814 tcp->u_rval = -1;
1815 u_error = -r9;
1816 }
1817 else {
1818 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001819 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001820#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001821 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1822 tcp->u_rval = -1;
1823 u_error = -r10;
1824 }
1825 else {
1826 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001827 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001828#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001829 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001830 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1831 return -1;
1832 if (check_errno && rval < 0 && rval > -nerrnos) {
1833 tcp->u_rval = -1;
1834 u_error = -rval;
1835 }
1836 else {
1837 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001838 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001839#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001840 if (check_errno && is_negated_errno(r3)) {
1841 tcp->u_rval = -1;
1842 u_error = -r3;
1843 }
1844 else {
1845 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001846 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001847#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001848 tcp->u_error = u_error;
1849 return 1;
1850}
1851
1852static void
1853dumpio(struct tcb *tcp)
1854{
1855 if (syserror(tcp))
1856 return;
1857 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1858 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001859 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001860 return;
1861 if (sysent[tcp->scno].sys_func == printargs)
1862 return;
1863 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1864 if (sysent[tcp->scno].sys_func == sys_read ||
1865 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001866 sysent[tcp->scno].sys_func == sys_recv ||
1867 sysent[tcp->scno].sys_func == sys_recvfrom)
1868 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1869 else if (sysent[tcp->scno].sys_func == sys_readv)
1870 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1871 return;
1872 }
1873 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1874 if (sysent[tcp->scno].sys_func == sys_write ||
1875 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001876 sysent[tcp->scno].sys_func == sys_send ||
1877 sysent[tcp->scno].sys_func == sys_sendto)
1878 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1879 else if (sysent[tcp->scno].sys_func == sys_writev)
1880 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1881 return;
1882 }
1883}
1884
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001885static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001886trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001887{
1888 int sys_res;
1889 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001890 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001891 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001892
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001893 /* Measure the exit time as early as possible to avoid errors. */
1894 if (dtime || cflag)
1895 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001896
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001897#if SUPPORTED_PERSONALITIES > 1
1898 update_personality(tcp, tcp->currpers);
1899#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001900 res = get_syscall_result(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001901 if (res == 0)
1902 return res;
1903 if (res == 1)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001904 res = syscall_fixup_on_sysexit(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001905 if (res == 0)
1906 return res;
1907 if (res == 1)
1908 res = get_error(tcp);
1909 if (res == 0)
1910 return res;
1911 if (res == 1)
1912 internal_syscall(tcp);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001913
Grant Edwards8a082772011-04-07 20:25:40 +00001914 if (res == 1 && filtered(tcp)) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001915 goto ret;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001916 }
1917
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001918 /* TODO: TCB_REPRINT is probably not necessary:
1919 * we can determine whether reprinting is needed
1920 * by examining printing_tcp. Something like:
1921 * if not in -ff mode, and printing_tcp != tcp,
1922 * then the log is not currenlty ends with *our*
1923 * syscall entry output, but with something else,
1924 * and we need to reprint.
1925 * If we'd implement this, printing_tcp = tcp
1926 * assignments in code below can be made more logical.
1927 */
1928
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001929 if (tcp->flags & TCB_REPRINT) {
1930 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001931 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001932 tprintf("<... syscall_%lu resumed> ", tcp->scno);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001933 else
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001934 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001935 }
1936
1937 if (cflag) {
1938 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02001939 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02001940 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001941 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001942 }
1943 }
1944
1945 if (res != 1) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001946 printing_tcp = tcp;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001947 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001948 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01001949 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001950 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001951 tcp->flags &= ~TCB_INSYSCALL;
1952 return res;
1953 }
1954
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001955 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001956 || (qual_flags[tcp->scno] & QUAL_RAW)) {
1957 printing_tcp = tcp;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001958 sys_res = printargs(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001959 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001960 /* FIXME: not_failing_only (IOW, option -z) is broken:
1961 * failure of syscall is known only after syscall return.
1962 * Thus we end up with something like this on, say, ENOENT:
1963 * open("doesnt_exist", O_RDONLY <unfinished ...>
1964 * {next syscall decode}
1965 * whereas the intended result is that open(...) line
1966 * is not shown at all.
1967 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001968 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02001969 goto ret; /* ignore failed syscalls */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001970 printing_tcp = tcp;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001971 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
1972 }
1973
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001974 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001975 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02001976 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001977 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001978 qual_flags[tcp->scno] & QUAL_RAW) {
1979 if (u_error)
1980 tprintf("= -1 (errno %ld)", u_error);
1981 else
1982 tprintf("= %#lx", tcp->u_rval);
1983 }
1984 else if (!(sys_res & RVAL_NONE) && u_error) {
1985 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01001986 /* Blocked signals do not interrupt any syscalls.
1987 * In this case syscalls don't return ERESTARTfoo codes.
1988 *
1989 * Deadly signals set to SIG_DFL interrupt syscalls
1990 * and kill the process regardless of which of the codes below
1991 * is returned by the interrupted syscall.
1992 * In some cases, kernel forces a kernel-generated deadly
1993 * signal to be unblocked and set to SIG_DFL (and thus cause
1994 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
1995 * or SIGILL. (The alternative is to leave process spinning
1996 * forever on the faulty instruction - not useful).
1997 *
1998 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
1999 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2000 * but kernel will always restart them.
2001 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002002 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002003 /* Most common type of signal-interrupted syscall exit code.
2004 * The system call will be restarted with the same arguments
2005 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2006 */
2007 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002008 break;
2009 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002010 /* Rare. For example, fork() returns this if interrupted.
2011 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2012 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002013 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002014 break;
2015 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002016 /* pause(), rt_sigsuspend() etc use this code.
2017 * SA_RESTART is ignored (assumed not set):
2018 * syscall won't restart (will return EINTR instead)
2019 * even after signal with SA_RESTART set.
2020 * However, after SIG_IGN or SIG_DFL signal it will.
2021 */
2022 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002023 break;
2024 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002025 /* Syscalls like nanosleep(), poll() which can't be
2026 * restarted with their original arguments use this
2027 * code. Kernel will execute restart_syscall() instead,
2028 * which changes arguments before restarting syscall.
2029 * SA_RESTART is ignored (assumed not set) similarly
2030 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2031 * since restart data is saved in "restart block"
2032 * in task struct, and if signal handler uses a syscall
2033 * which in turn saves another such restart block,
2034 * old data is lost and restart becomes impossible)
2035 */
2036 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002037 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002038 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002039 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002040 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002041 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002042 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002043 strerror(u_error));
2044 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002045 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002046 strerror(u_error));
2047 break;
2048 }
2049 if ((sys_res & RVAL_STR) && tcp->auxstr)
2050 tprintf(" (%s)", tcp->auxstr);
2051 }
2052 else {
2053 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002054 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002055 else {
2056 switch (sys_res & RVAL_MASK) {
2057 case RVAL_HEX:
2058 tprintf("= %#lx", tcp->u_rval);
2059 break;
2060 case RVAL_OCTAL:
2061 tprintf("= %#lo", tcp->u_rval);
2062 break;
2063 case RVAL_UDECIMAL:
2064 tprintf("= %lu", tcp->u_rval);
2065 break;
2066 case RVAL_DECIMAL:
2067 tprintf("= %ld", tcp->u_rval);
2068 break;
2069#ifdef HAVE_LONG_LONG
2070 case RVAL_LHEX:
2071 tprintf("= %#llx", tcp->u_lrval);
2072 break;
2073 case RVAL_LOCTAL:
2074 tprintf("= %#llo", tcp->u_lrval);
2075 break;
2076 case RVAL_LUDECIMAL:
2077 tprintf("= %llu", tcp->u_lrval);
2078 break;
2079 case RVAL_LDECIMAL:
2080 tprintf("= %lld", tcp->u_lrval);
2081 break;
2082#endif
2083 default:
2084 fprintf(stderr,
2085 "invalid rval format\n");
2086 break;
2087 }
2088 }
2089 if ((sys_res & RVAL_STR) && tcp->auxstr)
2090 tprintf(" (%s)", tcp->auxstr);
2091 }
2092 if (dtime) {
2093 tv_sub(&tv, &tv, &tcp->etime);
2094 tprintf(" <%ld.%06ld>",
2095 (long) tv.tv_sec, (long) tv.tv_usec);
2096 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002097 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002098 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002099 line_ended();
2100
Denys Vlasenko3b738812011-08-22 02:06:35 +02002101 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002102 tcp->flags &= ~TCB_INSYSCALL;
2103 return 0;
2104}
2105
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002106int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002107trace_syscall(struct tcb *tcp)
2108{
2109 return exiting(tcp) ?
2110 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2111}