blob: 3ee44175d00805d3529a978816b3b31ca792c829 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000032 */
33
34#include "defs.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000035#include <sys/user.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000036#include <sys/param.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000037
Wichert Akkerman15dea971999-10-06 13:06:34 +000038#ifdef HAVE_SYS_REG_H
Denys Vlasenko523635f2012-02-25 02:44:25 +010039# include <sys/reg.h>
40# ifndef PTRACE_PEEKUSR
41# define PTRACE_PEEKUSR PTRACE_PEEKUSER
42# endif
Wichert Akkermanfaf72222000-02-19 23:59:03 +000043#elif defined(HAVE_LINUX_PTRACE_H)
Denys Vlasenko523635f2012-02-25 02:44:25 +010044# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000045# ifdef HAVE_STRUCT_IA64_FPREG
46# define ia64_fpreg XXX_ia64_fpreg
47# endif
48# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
49# define pt_all_user_regs XXX_pt_all_user_regs
50# endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010051# include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000052# undef ia64_fpreg
53# undef pt_all_user_regs
Wichert Akkerman15dea971999-10-06 13:06:34 +000054#endif
55
Denys Vlasenko84703742012-02-25 02:38:52 +010056#if defined(SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +000057# undef PTRACE_GETREGS
58# define PTRACE_GETREGS PTRACE_GETREGS64
59# undef PTRACE_SETREGS
60# define PTRACE_SETREGS PTRACE_SETREGS64
Denys Vlasenko84703742012-02-25 02:38:52 +010061#endif
Roland McGrath6d1a65c2004-07-12 07:44:08 +000062
Denys Vlasenko84703742012-02-25 02:38:52 +010063#if defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000064# include <asm/ptrace_offsets.h>
65# include <asm/rse.h>
66#endif
67
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000068#ifndef ERESTARTSYS
Denys Vlasenko523635f2012-02-25 02:44:25 +010069# define ERESTARTSYS 512
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000070#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010071#ifndef ERESTARTNOINTR
Denys Vlasenko523635f2012-02-25 02:44:25 +010072# define ERESTARTNOINTR 513
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000073#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010074#ifndef ERESTARTNOHAND
75# define ERESTARTNOHAND 514 /* restart if no handler */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000076#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010077#ifndef ERESTART_RESTARTBLOCK
Denys Vlasenko523635f2012-02-25 02:44:25 +010078# define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
Roland McGrath9c555e72003-07-09 09:47:59 +000079#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010080
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000081#ifndef NSIG
Denys Vlasenko523635f2012-02-25 02:44:25 +010082# warning: NSIG is not defined, using 32
83# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000084#endif
85#ifdef ARM
Denys Vlasenko041b3ee2011-08-18 12:48:56 +020086/* Ugh. Is this really correct? ARM has no RT signals?! */
Denys Vlasenko523635f2012-02-25 02:44:25 +010087# undef NSIG
88# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000089#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000090
91#include "syscall.h"
92
93/* Define these shorthand notations to simplify the syscallent files. */
Roland McGrath2fe7b132005-07-05 03:25:35 +000094#define TD TRACE_DESC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000095#define TF TRACE_FILE
96#define TI TRACE_IPC
97#define TN TRACE_NETWORK
98#define TP TRACE_PROCESS
99#define TS TRACE_SIGNAL
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000100#define NF SYSCALL_NEVER_FAILS
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200101#define MA MAX_ARGS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102
Roland McGrathee36ce12004-09-04 03:53:10 +0000103static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000104#include "syscallent.h"
105};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000106
107#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000108static const struct sysent sysent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100109# include "syscallent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000110};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200111#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000112
113#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000114static const struct sysent sysent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100115# include "syscallent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000116};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200117#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000118
119/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000120#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000121#undef TF
122#undef TI
123#undef TN
124#undef TP
125#undef TS
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000126#undef NF
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200127#undef MA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000128
Denys Vlasenko39fca622011-08-20 02:12:33 +0200129/*
130 * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
131 * program `ioctlsort', such that the list is sorted by the `code' field.
132 * This has the side-effect of resolving the _IO.. macros into
133 * plain integers, eliminating the need to include here everything
134 * in "/usr/include".
135 */
136
Roland McGrathee36ce12004-09-04 03:53:10 +0000137static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000138#include "errnoent.h"
139};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200140static const char *const signalent0[] = {
141#include "signalent.h"
142};
143static const struct ioctlent ioctlent0[] = {
144#include "ioctlent.h"
145};
146enum { nsyscalls0 = ARRAY_SIZE(sysent0) };
147enum { nerrnos0 = ARRAY_SIZE(errnoent0) };
148enum { nsignals0 = ARRAY_SIZE(signalent0) };
149enum { nioctlents0 = ARRAY_SIZE(ioctlent0) };
150int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000151
152#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000153static const char *const errnoent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100154# include "errnoent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000155};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200156static const char *const signalent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100157# include "signalent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200158};
159static const struct ioctlent ioctlent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100160# include "ioctlent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200161};
162enum { nsyscalls1 = ARRAY_SIZE(sysent1) };
163enum { nerrnos1 = ARRAY_SIZE(errnoent1) };
164enum { nsignals1 = ARRAY_SIZE(signalent1) };
165enum { nioctlents1 = ARRAY_SIZE(ioctlent1) };
166int qual_flags1[MAX_QUALS];
167#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000168
169#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000170static const char *const errnoent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100171# include "errnoent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000172};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200173static const char *const signalent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100174# include "signalent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200175};
176static const struct ioctlent ioctlent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100177# include "ioctlent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200178};
179enum { nsyscalls2 = ARRAY_SIZE(sysent2) };
180enum { nerrnos2 = ARRAY_SIZE(errnoent2) };
181enum { nsignals2 = ARRAY_SIZE(signalent2) };
182enum { nioctlents2 = ARRAY_SIZE(ioctlent2) };
183int qual_flags2[MAX_QUALS];
184#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000185
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100186const struct sysent *sysent = sysent0;
187const char *const *errnoent = errnoent0;
188const char *const *signalent = signalent0;
189const struct ioctlent *ioctlent = ioctlent0;
190unsigned nsyscalls = nsyscalls0;
191unsigned nerrnos = nerrnos0;
192unsigned nsignals = nsignals0;
193unsigned nioctlents = nioctlents0;
194int *qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000195
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100196#if SUPPORTED_PERSONALITIES > 1
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000197int current_personality;
198
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000199const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
200 PERSONALITY0_WORDSIZE,
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000201 PERSONALITY1_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100202# if SUPPORTED_PERSONALITIES > 2
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000203 PERSONALITY2_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100204# endif
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200205};
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000206
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200207void
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000208set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000209{
210 switch (personality) {
211 case 0:
212 errnoent = errnoent0;
213 nerrnos = nerrnos0;
214 sysent = sysent0;
215 nsyscalls = nsyscalls0;
216 ioctlent = ioctlent0;
217 nioctlents = nioctlents0;
218 signalent = signalent0;
219 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000220 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000221 break;
222
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000223 case 1:
224 errnoent = errnoent1;
225 nerrnos = nerrnos1;
226 sysent = sysent1;
227 nsyscalls = nsyscalls1;
228 ioctlent = ioctlent1;
229 nioctlents = nioctlents1;
230 signalent = signalent1;
231 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000232 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000233 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000234
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100235# if SUPPORTED_PERSONALITIES >= 3
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000236 case 2:
237 errnoent = errnoent2;
238 nerrnos = nerrnos2;
239 sysent = sysent2;
240 nsyscalls = nsyscalls2;
241 ioctlent = ioctlent2;
242 nioctlents = nioctlents2;
243 signalent = signalent2;
244 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000245 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000246 break;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100247# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000248 }
249
250 current_personality = personality;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000251}
252
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000253static void
254update_personality(struct tcb *tcp, int personality)
255{
256 if (personality == current_personality)
257 return;
258 set_personality(personality);
259
260 if (personality == tcp->currpers)
261 return;
262 tcp->currpers = personality;
263
Denys Vlasenko523635f2012-02-25 02:44:25 +0100264# if defined(POWERPC64) || defined(X86_64)
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000265 if (!qflag) {
266 static const char *const names[] = {"64 bit", "32 bit"};
267 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
268 tcp->pid, names[personality]);
269 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100270# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000271}
272#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000273
Roland McGrath9797ceb2002-12-30 10:23:00 +0000274static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000275
Roland McGrathe10e62a2004-09-04 04:20:43 +0000276static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000277 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000278 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000279 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000280 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000281} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000282 { QUAL_TRACE, "trace", qual_syscall, "system call" },
283 { QUAL_TRACE, "t", qual_syscall, "system call" },
284 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
285 { QUAL_ABBREV, "a", qual_syscall, "system call" },
286 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
287 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
288 { QUAL_RAW, "raw", qual_syscall, "system call" },
289 { QUAL_RAW, "x", qual_syscall, "system call" },
290 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
291 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
292 { QUAL_SIGNAL, "s", qual_signal, "signal" },
293 { QUAL_FAULT, "fault", qual_fault, "fault" },
294 { QUAL_FAULT, "faults", qual_fault, "fault" },
295 { QUAL_FAULT, "m", qual_fault, "fault" },
296 { QUAL_READ, "read", qual_desc, "descriptor" },
297 { QUAL_READ, "reads", qual_desc, "descriptor" },
298 { QUAL_READ, "r", qual_desc, "descriptor" },
299 { QUAL_WRITE, "write", qual_desc, "descriptor" },
300 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
301 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000302 { 0, NULL, NULL, NULL },
303};
304
Roland McGrath9797ceb2002-12-30 10:23:00 +0000305static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000306qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000307{
Roland McGrath138c6a32006-01-12 09:50:49 +0000308 if (pers == 0 || pers < 0) {
309 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000310 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000311 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000312 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000313 }
314
315#if SUPPORTED_PERSONALITIES >= 2
316 if (pers == 1 || pers < 0) {
317 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000318 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000319 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000320 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000321 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100322#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000323
324#if SUPPORTED_PERSONALITIES >= 3
325 if (pers == 2 || pers < 0) {
326 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000327 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000328 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000329 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000330 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100331#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000332}
333
334static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000335qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000336{
337 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000338 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000339
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000340 if (isdigit((unsigned char)*s)) {
341 int i = atoi(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000342 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000343 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000344 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000345 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000346 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000347 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000348 if (strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000349 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000350 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000351 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000352
353#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000354 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000355 if (strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000356 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000357 rc = 0;
358 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100359#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000360
361#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000362 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000363 if (strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000364 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000365 rc = 0;
366 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100367#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000368
Roland McGrathfe6b3522005-02-02 04:40:11 +0000369 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000370}
371
372static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000373qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000374{
375 int i;
376 char buf[32];
377
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000378 if (isdigit((unsigned char)*s)) {
379 int signo = atoi(s);
380 if (signo < 0 || signo >= MAX_QUALS)
381 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000382 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000383 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000384 }
Roland McGrathd62b6712004-03-02 06:52:01 +0000385 if (strlen(s) >= sizeof buf)
Roland McGrathfe6b3522005-02-02 04:40:11 +0000386 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000387 strcpy(buf, s);
388 s = buf;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000389 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000390 s += 3;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000391 for (i = 0; i <= NSIG; i++)
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000392 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000393 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000394 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000395 }
Roland McGrath76421df2005-02-02 03:51:18 +0000396 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000397}
398
399static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000400qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000401{
402 return -1;
403}
404
405static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000406qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000407{
Roland McGrath48a035f2006-01-12 09:45:56 +0000408 if (isdigit((unsigned char)*s)) {
Roland McGrathfe6b3522005-02-02 04:40:11 +0000409 int desc = atoi(s);
410 if (desc < 0 || desc >= MAX_QUALS)
411 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000412 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000413 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000414 }
415 return -1;
416}
417
418static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000419lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000420{
421 if (strcmp(s, "file") == 0)
422 return TRACE_FILE;
423 if (strcmp(s, "ipc") == 0)
424 return TRACE_IPC;
425 if (strcmp(s, "network") == 0)
426 return TRACE_NETWORK;
427 if (strcmp(s, "process") == 0)
428 return TRACE_PROCESS;
429 if (strcmp(s, "signal") == 0)
430 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000431 if (strcmp(s, "desc") == 0)
432 return TRACE_DESC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000433 return -1;
434}
435
436void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000437qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000438{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000439 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000440 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000441 char *copy;
442 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000443 int i, n;
444
445 opt = &qual_options[0];
446 for (i = 0; (p = qual_options[i].option_name); i++) {
447 n = strlen(p);
448 if (strncmp(s, p, n) == 0 && s[n] == '=') {
449 opt = &qual_options[i];
450 s += n + 1;
451 break;
452 }
453 }
454 not = 0;
455 if (*s == '!') {
456 not = 1;
457 s++;
458 }
459 if (strcmp(s, "none") == 0) {
460 not = 1 - not;
461 s = "all";
462 }
463 if (strcmp(s, "all") == 0) {
464 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000465 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000466 }
467 return;
468 }
469 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000470 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000471 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200472 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200473 if (!copy)
474 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000475 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000476 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000477 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000478 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000479 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000480
481#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000482 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000483 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000484 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100485#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000486
487#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000488 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000489 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000490 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100491#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000492
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000493 continue;
494 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000495 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100496 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000497 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000498 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000499 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000500 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000501 return;
502}
503
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000504#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000505static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000506decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000507{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000508 unsigned long addr;
509 unsigned int i, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000510
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000511 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
512 return;
513
514 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
515 addr = tcp->u_arg[1];
516 tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100517 size = current_wordsize;
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000518 for (i = 0; i < tcp->u_nargs; ++i) {
519 if (size == sizeof(int)) {
520 unsigned int arg;
521 if (umove(tcp, addr, &arg) < 0)
522 arg = 0;
523 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000524 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000525 else {
526 unsigned long arg;
527 if (umove(tcp, addr, &arg) < 0)
528 arg = 0;
529 tcp->u_arg[i] = arg;
530 }
531 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000532 }
533}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000534#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400535
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000536#ifdef SYS_ipc_subcall
537static void
538decode_ipc_subcall(struct tcb *tcp)
539{
540 unsigned int i;
541
542 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
543 return;
544
545 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
546 tcp->u_nargs = sysent[tcp->scno].nargs;
547 for (i = 0; i < tcp->u_nargs; i++)
548 tcp->u_arg[i] = tcp->u_arg[i + 1];
549}
550#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000551
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200552int
553printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000554{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200555 if (entering(tcp)) {
556 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000557
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200558 for (i = 0; i < tcp->u_nargs; i++)
559 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
560 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000561 return 0;
562}
563
Denys Vlasenko72879c62012-02-27 14:18:02 +0100564int
565printargs_lu(struct tcb *tcp)
566{
567 if (entering(tcp)) {
568 int i;
569
570 for (i = 0; i < tcp->u_nargs; i++)
571 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
572 }
573 return 0;
574}
575
576int
577printargs_ld(struct tcb *tcp)
578{
579 if (entering(tcp)) {
580 int i;
581
582 for (i = 0; i < tcp->u_nargs; i++)
583 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
584 }
585 return 0;
586}
587
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200588long
589getrval2(struct tcb *tcp)
590{
591 long val = -1;
592
Denys Vlasenko523635f2012-02-25 02:44:25 +0100593#if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200594 struct pt_regs regs;
595 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
596 return -1;
597 val = regs.u_regs[U_REG_O1];
598#elif defined(SH)
599 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
600 return -1;
601#elif defined(IA64)
602 if (upeek(tcp, PT_R9, &val) < 0)
603 return -1;
604#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200605
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200606 return val;
607}
608
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200609int
610is_restart_error(struct tcb *tcp)
611{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200612 switch (tcp->u_error) {
613 case ERESTARTSYS:
614 case ERESTARTNOINTR:
615 case ERESTARTNOHAND:
616 case ERESTART_RESTARTBLOCK:
617 return 1;
618 default:
619 break;
620 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200621 return 0;
622}
623
Denys Vlasenko523635f2012-02-25 02:44:25 +0100624#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100625struct pt_regs i386_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100626#elif defined(X86_64)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100627/*
628 * On 32 bits, pt_regs and user_regs_struct are the same,
629 * but on 64 bits, user_regs_struct has six more fields:
630 * fs_base, gs_base, ds, es, fs, gs.
631 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
632 */
633static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100634#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200635long r8, r10, psr; /* TODO: make static? */
636long ia32 = 0; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100637#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +0200638static long result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100639#elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200640static long d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100641#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200642static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100643#elif defined(ARM)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200644static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100645#elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200646static long r0;
647static long a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100648#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200649static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100650#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200651static struct pt_regs regs;
652static unsigned long trap;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100653#elif defined(LINUX_MIPSN32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200654static long long a3;
655static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100656#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200657static long a3;
658static long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100659#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200660static long gpr2;
661static long pc;
662static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100663#elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200664static long r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100665#elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200666static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100667#elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200668static long r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100669#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200670static long r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100671#elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200672static long r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100673#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000674
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200675/* Returns:
676 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
677 * 1: ok, continue in trace_syscall().
678 * other: error, trace_syscall() should print error indicator
679 * ("????" etc) and bail out.
680 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100681static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200682get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000683{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000684 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000685
Denys Vlasenko523635f2012-02-25 02:44:25 +0100686#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000687 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200688 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000689
690 if (syscall_mode != -ENOSYS) {
691 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000692 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000693 */
694 scno = syscall_mode;
695 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000696 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000697 * Old style of "passing" the scno via the SVC instruction.
698 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000699 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200700 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200701 static const int gpr_offset[16] = {
702 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
703 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
704 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
705 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
706 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000707
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000708 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000709 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000710 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000711 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000712 if (errno) {
713 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000714 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000715 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000716
717 /*
718 * We have to check if the SVC got executed directly or via an
719 * EXECUTE instruction. In case of EXECUTE it is necessary to do
720 * instruction decoding to derive the system call number.
721 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
722 * so that this doesn't work if a SVC opcode is part of an EXECUTE
723 * opcode. Since there is no way to find out the opcode size this
724 * is the best we can do...
725 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000726 if ((opcode & 0xff00) == 0x0a00) {
727 /* SVC opcode */
728 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000729 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000730 else {
731 /* SVC got executed by EXECUTE instruction */
732
733 /*
734 * Do instruction decoding of EXECUTE. If you really want to
735 * understand this, read the Principles of Operations.
736 */
737 svc_addr = (void *) (opcode & 0xfff);
738
739 tmp = 0;
740 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000741 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000742 return -1;
743 svc_addr += tmp;
744
745 tmp = 0;
746 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000747 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000748 return -1;
749 svc_addr += tmp;
750
Denys Vlasenkofb036672009-01-23 16:30:26 +0000751 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000752 if (errno)
753 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100754# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000755 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100756# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000757 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100758# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000759 tmp = 0;
760 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000761 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000762 return -1;
763
764 scno = (scno | tmp) & 0xff;
765 }
766 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100767#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000768 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000769 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100770# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200771 /* TODO: speed up strace by not doing this at every syscall.
772 * We only need to do it after execve.
773 */
774 int currpers;
775 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200776
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200777 /* Check for 64/32 bit mode. */
778 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
779 return -1;
780 /* SF is bit 0 of MSR */
781 if (val < 0)
782 currpers = 0;
783 else
784 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000785 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100786# endif
787#elif defined(AVR32)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200788 /* Read complete register set in one go. */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000789 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
790 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200791 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100792#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000793 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000794 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100795#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200796 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000797 return -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200798 scno = i386_regs.orig_eax;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100799#elif defined(X86_64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200800 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200801 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
802 return -1;
803 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +0000804
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200805 /* Check CS register value. On x86-64 linux it is:
806 * 0x33 for long mode (64 bit)
807 * 0x23 for compatibility mode (32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200808 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200809 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200810 case 0x23: currpers = 1; break;
811 case 0x33: currpers = 0; break;
812 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200813 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200814 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200815 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200816 currpers = current_personality;
817 break;
818 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100819# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200820 /* This version analyzes the opcode of a syscall instruction.
821 * (int 0x80 on i386 vs. syscall on x86-64)
822 * It works, but is too complicated.
823 */
824 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +0000825
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200826 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +0000827
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200828 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
829 rip -= 2;
830 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +0000831
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200832 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200833 if (errno)
834 fprintf(stderr, "ptrace_peektext failed: %s\n",
835 strerror(errno));
836 switch (call & 0xffff) {
837 /* x86-64: syscall = 0x0f 0x05 */
838 case 0x050f: currpers = 0; break;
839 /* i386: int 0x80 = 0xcd 0x80 */
840 case 0x80cd: currpers = 1; break;
841 default:
842 currpers = current_personality;
843 fprintf(stderr,
844 "Unknown syscall opcode (0x%04X) while "
845 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200846 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200847 break;
848 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100849# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000850 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100851#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000852# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200853 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000854 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200855 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200856 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200857 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000858 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200859 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000860 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200861 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100862#elif defined(ARM)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200863 /* Read complete register set in one go. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000864 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +0000865 return -1;
866
867 /*
868 * We only need to grab the syscall number on syscall entry.
869 */
870 if (regs.ARM_ip == 0) {
871 /*
872 * Note: we only deal with only 32-bit CPUs here.
873 */
874 if (regs.ARM_cpsr & 0x20) {
875 /*
876 * Get the Thumb-mode system call number
877 */
878 scno = regs.ARM_r7;
879 } else {
880 /*
881 * Get the ARM-mode system call number
882 */
883 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000884 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +0000885 if (errno)
886 return -1;
887
Roland McGrathf691bd22006-04-25 07:34:41 +0000888 /* Handle the EABI syscall convention. We do not
889 bother converting structures between the two
890 ABIs, but basic functionality should work even
891 if strace and the traced program have different
892 ABIs. */
893 if (scno == 0xef000000) {
894 scno = regs.ARM_r7;
895 } else {
896 if ((scno & 0x0ff00000) != 0x0f900000) {
897 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
898 scno);
899 return -1;
900 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000901
Roland McGrathf691bd22006-04-25 07:34:41 +0000902 /*
903 * Fixup the syscall number
904 */
905 scno &= 0x000fffff;
906 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000907 }
Roland McGrath56703312008-05-20 01:35:55 +0000908 if (scno & 0x0f0000) {
909 /*
910 * Handle ARM specific syscall
911 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000912 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +0000913 scno &= 0x0000ffff;
914 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000915 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +0000916
Roland McGrath0f87c492003-06-03 23:29:04 +0000917 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200918 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
919 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000920 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100921#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000922 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000923 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100924#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +0000925 unsigned long long regs[38];
926
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200927 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +0000928 return -1;
929 a3 = regs[REG_A3];
930 r2 = regs[REG_V0];
931
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200932 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200933 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200934 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100935 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200936 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000937 return 0;
938 }
Roland McGrath542c2c62008-05-20 01:11:56 +0000939 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100940#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000941 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000942 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200943 if (upeek(tcp, REG_V0, &scno) < 0)
944 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000945
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200946 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200947 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100948 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200949 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000950 return 0;
951 }
Wichert Akkermanf90da011999-10-31 21:15:38 +0000952 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100953#elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000954 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000955 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200956 if (upeek(tcp, REG_R0, &scno) < 0)
957 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000958
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200959 /*
960 * Do some sanity checks to figure out if it's
961 * really a syscall entry
962 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200963 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200964 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100965 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200966 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000967 return 0;
968 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000969 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100970#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000971 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000972 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000973 return -1;
974
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200975 /* Disassemble the syscall trap. */
976 /* Retrieve the syscall trap instruction. */
977 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100978# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200979 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
980 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100981# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200982 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100983# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200984 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +0000985 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200986
987 /* Disassemble the trap to see what personality to use. */
988 switch (trap) {
989 case 0x91d02010:
990 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000991 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200992 break;
993 case 0x91d0206d:
994 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000995 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200996 break;
997 case 0x91d02000:
998 /* SunOS syscall trap. (pers 1) */
999 fprintf(stderr, "syscall: SunOS no support\n");
1000 return -1;
1001 case 0x91d02008:
1002 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001003 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001004 break;
1005 case 0x91d02009:
1006 /* NetBSD/FreeBSD syscall trap. */
1007 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1008 return -1;
1009 case 0x91d02027:
1010 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001011 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001012 break;
1013 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001014# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001015 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001016# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001017 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001018# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001019 return -1;
1020 }
1021
1022 /* Extract the system call number from the registers. */
1023 if (trap == 0x91d02027)
1024 scno = 156;
1025 else
1026 scno = regs.u_regs[U_REG_G1];
1027 if (scno == 0) {
1028 scno = regs.u_regs[U_REG_O0];
1029 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1030 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001031#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001032 if (upeek(tcp, PT_GR20, &scno) < 0)
1033 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001034#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001035 /*
1036 * In the new syscall ABI, the system call number is in R3.
1037 */
1038 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1039 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001040
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001041 if (scno < 0) {
1042 /* Odd as it may seem, a glibc bug has been known to cause
1043 glibc to issue bogus negative syscall numbers. So for
1044 our purposes, make strace print what it *should* have been */
1045 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001046 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001047 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001048 "Detected glibc bug: bogus system call"
1049 " number = %ld, correcting to %ld\n",
1050 scno,
1051 correct_scno);
1052 scno = correct_scno;
1053 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001054#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001055 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001056 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001057 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001058#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001059 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1060 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001061#elif defined(TILE)
Chris Metcalfc8c66982009-12-28 10:00:15 -05001062 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1063 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001064#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001065 if (upeek(tcp, 0, &scno) < 0)
1066 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001067#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001068
Denys Vlasenko523635f2012-02-25 02:44:25 +01001069#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001070 /* new syscall ABI returns result in R0 */
1071 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1072 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001073#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001074 /* ABI defines result returned in r9 */
1075 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1076 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001077#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001078
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001079 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001080 return 1;
1081}
1082
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001083/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001084 * Returns:
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001085 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
Roland McGratheb9e2e82009-06-02 16:49:22 -07001086 * 1: ok, continue in trace_syscall().
1087 * other: error, trace_syscall() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001088 * ("????" etc) and bail out.
1089 */
Roland McGratha4d48532005-06-08 20:45:28 +00001090static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001091syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001092{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001093 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001094#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001095 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001096 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001097 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1098 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001099 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001100#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001101 {
1102 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001103 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001104 rax = (int)rax; /* sign extend from 32 bits */
1105 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001106 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001107 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1108 return 0;
1109 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001110 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001111#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001112 /* TODO: we already fetched PT_GPR2 in get_scno
1113 * and stored it in syscall_mode, reuse it here
1114 * instead of re-fetching?
1115 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001116 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001117 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001118 if (syscall_mode != -ENOSYS)
1119 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001120 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001121 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001122 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001123 return 0;
1124 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001125#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001126 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001127 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001128 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001129 if (d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001130 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001131 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001132 return 0;
1133 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001134#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001135 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001136 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001137 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001138 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001139 if (ia32 && r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001140 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001141 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001142 return 0;
1143 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001144#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001145 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001146 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001147 if (r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001148 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001149 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001150 return 0;
1151 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001152#elif defined(MICROBLAZE)
1153 if (upeek(tcp, 3 * 4, &r3) < 0)
1154 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001155 if (r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001156 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001157 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001158 return 0;
1159 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001160#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001161 return 1;
1162}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001163
Denys Vlasenko146b9442012-03-18 22:10:48 +01001164static void
1165internal_fork(struct tcb *tcp)
1166{
1167#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1168# define ARG_FLAGS 1
1169#else
1170# define ARG_FLAGS 0
1171#endif
1172#ifndef CLONE_UNTRACED
1173# define CLONE_UNTRACED 0x00800000
1174#endif
1175 if ((ptrace_setoptions
1176 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1177 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1178 return;
1179
1180 if (!followfork)
1181 return;
1182
1183 if (entering(tcp)) {
1184 /*
1185 * We won't see the new child if clone is called with
1186 * CLONE_UNTRACED, so we keep the same logic with that option
1187 * and don't trace it.
1188 */
1189 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1190 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1191 return;
1192 setbpt(tcp);
1193 } else {
1194 if (tcp->flags & TCB_BPTSET)
1195 clearbpt(tcp);
1196 }
1197}
1198
1199#if defined(TCB_WAITEXECVE)
1200static void
1201internal_exec(struct tcb *tcp)
1202{
1203 /* Maybe we have post-execve SIGTRAP suppressed? */
1204 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1205 return; /* yes, no need to do anything */
1206
1207 if (exiting(tcp) && syserror(tcp))
1208 /* Error in execve, no post-execve SIGTRAP expected */
1209 tcp->flags &= ~TCB_WAITEXECVE;
1210 else
1211 tcp->flags |= TCB_WAITEXECVE;
1212}
1213#endif
1214
1215static void
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001216internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001217{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001218 /*
1219 * We must always trace a few critical system calls in order to
1220 * correctly support following forks in the presence of tracing
1221 * qualifiers.
1222 */
1223 int (*func)();
1224
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001225 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001226 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001227
1228 func = sysent[tcp->scno].sys_func;
1229
1230 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001231 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001232 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001233 ) {
1234 internal_fork(tcp);
1235 return;
1236 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001237
Denys Vlasenko84703742012-02-25 02:38:52 +01001238#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001239 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001240# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001241 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001242# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001243 ) {
1244 internal_exec(tcp);
1245 return;
1246 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001247#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001248}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001249
Roland McGratha4d48532005-06-08 20:45:28 +00001250static int
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001251syscall_enter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001252{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001253 int i, nargs;
1254
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001255 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001256 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001257 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001258 nargs = tcp->u_nargs = MAX_ARGS;
1259
Denys Vlasenko523635f2012-02-25 02:44:25 +01001260#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001261 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001262 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1263 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001264#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001265 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001266 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1267 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001268#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001269 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001270 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001271 long rbs_end;
1272 /* be backwards compatible with kernel < 2.4.4... */
1273# ifndef PT_RBS_END
1274# define PT_RBS_END PT_AR_BSP
1275# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001276
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001277 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1278 return -1;
1279 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001280 return -1;
1281
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001282 sof = (cfm >> 0) & 0x7f;
1283 sol = (cfm >> 7) & 0x7f;
1284 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1285
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001286 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001287 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1288 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1289 return -1;
1290 }
1291 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001292 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1293 PT_R9 /* ECX = out1 */,
1294 PT_R10 /* EDX = out2 */,
1295 PT_R14 /* ESI = out3 */,
1296 PT_R15 /* EDI = out4 */,
1297 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001298
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001299 for (i = 0; i < nargs; ++i) {
1300 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1301 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001302 /* truncate away IVE sign-extension */
1303 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001304 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001305 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001306#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001307 /* N32 and N64 both use up to six registers. */
1308 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001309
1310 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1311 return -1;
1312
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001313 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001314 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001315# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001316 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001317# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001318 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001319#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001320 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001321 long sp;
1322
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001323 if (upeek(tcp, REG_SP, &sp) < 0)
1324 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001325 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001326 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1327 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001328 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001329 (char *)(tcp->u_arg + 4));
1330 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001331 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001332 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001333 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001334 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001335#elif defined(POWERPC)
1336# ifndef PT_ORIG_R3
1337# define PT_ORIG_R3 34
1338# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001339 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001340 if (upeek(tcp, (i==0) ?
1341 (sizeof(unsigned long) * PT_ORIG_R3) :
1342 ((i+PT_R3) * sizeof(unsigned long)),
1343 &tcp->u_arg[i]) < 0)
1344 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001345 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001346#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001347 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001348 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001349#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001350 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001351 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1352 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001353#elif defined(ARM)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001354 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001355 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001356#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001357 (void)i;
1358 (void)nargs;
1359 tcp->u_arg[0] = regs.r12;
1360 tcp->u_arg[1] = regs.r11;
1361 tcp->u_arg[2] = regs.r10;
1362 tcp->u_arg[3] = regs.r9;
1363 tcp->u_arg[4] = regs.r5;
1364 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001365#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001366 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 +02001367
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001368 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001369 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1370 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001371#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001372 static const int syscall_regs[MAX_ARGS] = {
1373 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1374 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001375 };
1376
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001377 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001378 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001379 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001380#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001381 int i;
1382 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001383 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001384
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001385 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001386 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1387 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001388#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001389 (void)i;
1390 (void)nargs;
1391 if (current_personality == 0) { /* x86-64 ABI */
1392 tcp->u_arg[0] = x86_64_regs.rdi;
1393 tcp->u_arg[1] = x86_64_regs.rsi;
1394 tcp->u_arg[2] = x86_64_regs.rdx;
1395 tcp->u_arg[3] = x86_64_regs.r10;
1396 tcp->u_arg[4] = x86_64_regs.r8;
1397 tcp->u_arg[5] = x86_64_regs.r9;
1398 } else { /* i386 ABI */
1399 /* Sign-extend lower 32 bits */
1400 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1401 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1402 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1403 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1404 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1405 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1406 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001407#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001408 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001409 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1410 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001411#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001412 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001413 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001414 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001415 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001416
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001417 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001418 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1419 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001420#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001421 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001422 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1423 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001424#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001425 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001426 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1427 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001428#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001429 (void)i;
1430 (void)nargs;
1431 tcp->u_arg[0] = i386_regs.ebx;
1432 tcp->u_arg[1] = i386_regs.ecx;
1433 tcp->u_arg[2] = i386_regs.edx;
1434 tcp->u_arg[3] = i386_regs.esi;
1435 tcp->u_arg[4] = i386_regs.edi;
1436 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001437#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001438 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001439 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1440 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001441#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001442 return 1;
1443}
1444
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001445static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001446trace_syscall_entering(struct tcb *tcp)
1447{
1448 int res, scno_good;
1449
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001450#if defined TCB_WAITEXECVE
1451 if (tcp->flags & TCB_WAITEXECVE) {
1452 /* This is the post-execve SIGTRAP. */
1453 tcp->flags &= ~TCB_WAITEXECVE;
1454 return 0;
1455 }
1456#endif
1457
Denys Vlasenko06602d92011-08-24 17:53:52 +02001458 scno_good = res = get_scno(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001459 if (res == 0)
1460 return res;
1461 if (res == 1)
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001462 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001463 if (res == 0)
1464 return res;
1465 if (res == 1)
1466 res = syscall_enter(tcp);
1467 if (res == 0)
1468 return res;
1469
1470 if (res != 1) {
1471 printleader(tcp);
1472 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001473 if (scno_good != 1)
1474 tprintf("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001475 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001476 tprintf("syscall_%lu(", tcp->scno);
1477 else
1478 tprintf("%s(", sysent[tcp->scno].sys_name);
1479 /*
1480 * " <unavailable>" will be added later by the code which
1481 * detects ptrace errors.
1482 */
1483 goto ret;
1484 }
1485
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001486#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1487 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001488# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001489 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001490 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001491 break;
1492 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001493# endif
1494# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001495 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001496 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001497 break;
1498 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001499# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001500 break;
1501 }
1502#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1503
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001504 internal_syscall(tcp);
1505
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001506 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001507 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1508 (tracing_paths && !pathtrace_match(tcp))) {
1509 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1510 return 0;
1511 }
1512
1513 tcp->flags &= ~TCB_FILTERED;
1514
1515 if (cflag == CFLAG_ONLY_STATS) {
1516 res = 0;
1517 goto ret;
1518 }
1519
1520 printleader(tcp);
1521 tcp->flags &= ~TCB_REPRINT;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001522 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001523 tprintf("syscall_%lu(", tcp->scno);
1524 else
1525 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001526 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001527 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1528 sysent[tcp->scno].sys_func != sys_exit))
1529 res = printargs(tcp);
1530 else
1531 res = (*sysent[tcp->scno].sys_func)(tcp);
1532
1533 if (fflush(tcp->outf) == EOF)
1534 return -1;
1535 ret:
1536 tcp->flags |= TCB_INSYSCALL;
1537 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001538 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001539 gettimeofday(&tcp->etime, NULL);
1540 return res;
1541}
1542
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001543/* Returns:
1544 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1545 * 1: ok, continue in trace_syscall().
1546 * other: error, trace_syscall() should print error indicator
1547 * ("????" etc) and bail out.
1548 */
1549static int
1550get_syscall_result(struct tcb *tcp)
1551{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001552#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001553 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1554 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001555#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001556# define SO_MASK 0x10000000
1557 {
1558 long flags;
1559 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1560 return -1;
1561 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &result) < 0)
1562 return -1;
1563 if (flags & SO_MASK)
1564 result = -result;
1565 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001566#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001567 /* Read complete register set in one go. */
1568 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1569 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001570#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001571 if (upeek(tcp, PT_R0, &r0) < 0)
1572 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001573#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001574 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001575 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001576#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001577 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001578 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001579#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001580# define IA64_PSR_IS ((long)1 << 34)
1581 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1582 ia32 = (psr & IA64_PSR_IS) != 0;
1583 if (upeek(tcp, PT_R8, &r8) < 0)
1584 return -1;
1585 if (upeek(tcp, PT_R10, &r10) < 0)
1586 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001587#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001588 /* Read complete register set in one go. */
1589 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1590 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001591#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001592 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1593 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001594#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001595 unsigned long long regs[38];
1596
1597 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1598 return -1;
1599 a3 = regs[REG_A3];
1600 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001601#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001602 if (upeek(tcp, REG_A3, &a3) < 0)
1603 return -1;
1604 if (upeek(tcp, REG_V0, &r2) < 0)
1605 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001606#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001607 if (upeek(tcp, REG_A3, &a3) < 0)
1608 return -1;
1609 if (upeek(tcp, REG_R0, &r0) < 0)
1610 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001611#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001612 /* Everything we need is in the current register set. */
1613 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1614 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001615#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001616 if (upeek(tcp, PT_GR28, &r28) < 0)
1617 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001618#elif defined(SH)
1619#elif defined(SH64)
1620#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001621 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1622 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001623#elif defined(TILE)
1624#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001625 if (upeek(tcp, 3 * 4, &r3) < 0)
1626 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001627#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001628
Denys Vlasenko523635f2012-02-25 02:44:25 +01001629#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001630 /* new syscall ABI returns result in R0 */
1631 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1632 return -1;
1633#elif defined(SH64)
1634 /* ABI defines result returned in r9 */
1635 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1636 return -1;
1637#endif
1638
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001639 return 1;
1640}
1641
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001642/* Called at each syscall exit.
1643 * Returns:
1644 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1645 * 1: ok, continue in trace_syscall().
1646 * other: error, trace_syscall() should print error indicator
1647 * ("????" etc) and bail out.
1648 */
1649static int
1650syscall_fixup_on_sysexit(struct tcb *tcp)
1651{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001652#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001653 if (syscall_mode != -ENOSYS)
1654 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001655 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001656 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1657 /*
1658 * Return from execve.
1659 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1660 * flag set for the post-execve SIGTRAP to see and reset.
1661 */
1662 gpr2 = 0;
1663 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001664#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001665 return 1;
1666}
1667
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001668/*
1669 * Check the syscall return value register value for whether it is
1670 * a negated errno code indicating an error, or a success return value.
1671 */
1672static inline int
1673is_negated_errno(unsigned long int val)
1674{
1675 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001676#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001677 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001678 val = (unsigned int) val;
1679 max = (unsigned int) max;
1680 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001681#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001682 return val > max;
1683}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001684
1685static int
1686get_error(struct tcb *tcp)
1687{
1688 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001689 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001690 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001691 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1692 check_errno = 0;
1693 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001694#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001695 if (check_errno && is_negated_errno(gpr2)) {
1696 tcp->u_rval = -1;
1697 u_error = -gpr2;
1698 }
1699 else {
1700 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001701 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001702#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001703 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001704 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001705 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001706 }
1707 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001708 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001709 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001710#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001711 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001712 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001713 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001714 }
1715 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001716 tcp->u_rval = x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001717 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001718#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001719 if (ia32) {
1720 int err;
1721
1722 err = (int)r8;
1723 if (check_errno && is_negated_errno(err)) {
1724 tcp->u_rval = -1;
1725 u_error = -err;
1726 }
1727 else {
1728 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001729 }
1730 } else {
1731 if (check_errno && r10) {
1732 tcp->u_rval = -1;
1733 u_error = r8;
1734 } else {
1735 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001736 }
1737 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001738#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001739 if (check_errno && a3) {
1740 tcp->u_rval = -1;
1741 u_error = r2;
1742 } else {
1743 tcp->u_rval = r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001744 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001745#elif defined(POWERPC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001746 if (check_errno && is_negated_errno(result)) {
1747 tcp->u_rval = -1;
1748 u_error = -result;
1749 }
1750 else {
1751 tcp->u_rval = result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001752 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001753#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001754 if (check_errno && is_negated_errno(d0)) {
1755 tcp->u_rval = -1;
1756 u_error = -d0;
1757 }
1758 else {
1759 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001760 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001761#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001762 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1763 tcp->u_rval = -1;
1764 u_error = -regs.ARM_r0;
1765 }
1766 else {
1767 tcp->u_rval = regs.ARM_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001768 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001769#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001770 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1771 tcp->u_rval = -1;
1772 u_error = -regs.r12;
1773 }
1774 else {
1775 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001776 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001777#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001778 if (check_errno && is_negated_errno(r0)) {
1779 tcp->u_rval = -1;
1780 u_error = -r0;
1781 } else {
1782 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001783 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001784#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001785 if (check_errno && a3) {
1786 tcp->u_rval = -1;
1787 u_error = r0;
1788 }
1789 else {
1790 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001791 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001792#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001793 if (check_errno && regs.psr & PSR_C) {
1794 tcp->u_rval = -1;
1795 u_error = regs.u_regs[U_REG_O0];
1796 }
1797 else {
1798 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001799 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001800#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001801 if (check_errno && regs.tstate & 0x1100000000UL) {
1802 tcp->u_rval = -1;
1803 u_error = regs.u_regs[U_REG_O0];
1804 }
1805 else {
1806 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001807 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001808#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001809 if (check_errno && is_negated_errno(r28)) {
1810 tcp->u_rval = -1;
1811 u_error = -r28;
1812 }
1813 else {
1814 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001815 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001816#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001817 if (check_errno && is_negated_errno(r0)) {
1818 tcp->u_rval = -1;
1819 u_error = -r0;
1820 }
1821 else {
1822 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001823 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001824#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001825 if (check_errno && is_negated_errno(r9)) {
1826 tcp->u_rval = -1;
1827 u_error = -r9;
1828 }
1829 else {
1830 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001831 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001832#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001833 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1834 tcp->u_rval = -1;
1835 u_error = -r10;
1836 }
1837 else {
1838 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001839 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001840#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001841 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001842 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1843 return -1;
1844 if (check_errno && rval < 0 && rval > -nerrnos) {
1845 tcp->u_rval = -1;
1846 u_error = -rval;
1847 }
1848 else {
1849 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001850 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001851#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001852 if (check_errno && is_negated_errno(r3)) {
1853 tcp->u_rval = -1;
1854 u_error = -r3;
1855 }
1856 else {
1857 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001858 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001859#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001860 tcp->u_error = u_error;
1861 return 1;
1862}
1863
1864static void
1865dumpio(struct tcb *tcp)
1866{
1867 if (syserror(tcp))
1868 return;
1869 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1870 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001871 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001872 return;
1873 if (sysent[tcp->scno].sys_func == printargs)
1874 return;
1875 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1876 if (sysent[tcp->scno].sys_func == sys_read ||
1877 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001878 sysent[tcp->scno].sys_func == sys_recv ||
1879 sysent[tcp->scno].sys_func == sys_recvfrom)
1880 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1881 else if (sysent[tcp->scno].sys_func == sys_readv)
1882 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1883 return;
1884 }
1885 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1886 if (sysent[tcp->scno].sys_func == sys_write ||
1887 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001888 sysent[tcp->scno].sys_func == sys_send ||
1889 sysent[tcp->scno].sys_func == sys_sendto)
1890 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1891 else if (sysent[tcp->scno].sys_func == sys_writev)
1892 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1893 return;
1894 }
1895}
1896
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001897static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001898trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001899{
1900 int sys_res;
1901 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001902 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001903 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001904
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001905 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001906 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001907 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001908
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001909#if SUPPORTED_PERSONALITIES > 1
1910 update_personality(tcp, tcp->currpers);
1911#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001912 res = get_syscall_result(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001913 if (res == 0)
1914 return res;
1915 if (res == 1)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001916 res = syscall_fixup_on_sysexit(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001917 if (res == 0)
1918 return res;
1919 if (res == 1)
1920 res = get_error(tcp);
1921 if (res == 0)
1922 return res;
1923 if (res == 1)
1924 internal_syscall(tcp);
Denys Vlasenko732d1bf2008-12-17 19:21:59 +00001925
Grant Edwards8a082772011-04-07 20:25:40 +00001926 if (res == 1 && filtered(tcp)) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001927 goto ret;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001928 }
1929
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001930 /* TODO: TCB_REPRINT is probably not necessary:
1931 * we can determine whether reprinting is needed
1932 * by examining printing_tcp. Something like:
1933 * if not in -ff mode, and printing_tcp != tcp,
1934 * then the log is not currenlty ends with *our*
1935 * syscall entry output, but with something else,
1936 * and we need to reprint.
1937 * If we'd implement this, printing_tcp = tcp
1938 * assignments in code below can be made more logical.
1939 */
1940
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001941 if (tcp->flags & TCB_REPRINT) {
1942 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001943 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001944 tprintf("<... syscall_%lu resumed> ", tcp->scno);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001945 else
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001946 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001947 }
1948
1949 if (cflag) {
1950 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02001951 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02001952 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001953 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001954 }
1955 }
1956
1957 if (res != 1) {
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001958 printing_tcp = tcp;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001959 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001960 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01001961 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001962 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001963 tcp->flags &= ~TCB_INSYSCALL;
1964 return res;
1965 }
1966
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001967 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001968 || (qual_flags[tcp->scno] & QUAL_RAW)) {
1969 printing_tcp = tcp;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001970 sys_res = printargs(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001971 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001972 /* FIXME: not_failing_only (IOW, option -z) is broken:
1973 * failure of syscall is known only after syscall return.
1974 * Thus we end up with something like this on, say, ENOENT:
1975 * open("doesnt_exist", O_RDONLY <unfinished ...>
1976 * {next syscall decode}
1977 * whereas the intended result is that open(...) line
1978 * is not shown at all.
1979 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001980 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02001981 goto ret; /* ignore failed syscalls */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001982 printing_tcp = tcp;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001983 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
1984 }
1985
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001986 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001987 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02001988 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001989 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001990 qual_flags[tcp->scno] & QUAL_RAW) {
1991 if (u_error)
1992 tprintf("= -1 (errno %ld)", u_error);
1993 else
1994 tprintf("= %#lx", tcp->u_rval);
1995 }
1996 else if (!(sys_res & RVAL_NONE) && u_error) {
1997 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01001998 /* Blocked signals do not interrupt any syscalls.
1999 * In this case syscalls don't return ERESTARTfoo codes.
2000 *
2001 * Deadly signals set to SIG_DFL interrupt syscalls
2002 * and kill the process regardless of which of the codes below
2003 * is returned by the interrupted syscall.
2004 * In some cases, kernel forces a kernel-generated deadly
2005 * signal to be unblocked and set to SIG_DFL (and thus cause
2006 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2007 * or SIGILL. (The alternative is to leave process spinning
2008 * forever on the faulty instruction - not useful).
2009 *
2010 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2011 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2012 * but kernel will always restart them.
2013 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002014 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002015 /* Most common type of signal-interrupted syscall exit code.
2016 * The system call will be restarted with the same arguments
2017 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2018 */
2019 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002020 break;
2021 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002022 /* Rare. For example, fork() returns this if interrupted.
2023 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2024 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002025 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002026 break;
2027 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002028 /* pause(), rt_sigsuspend() etc use this code.
2029 * SA_RESTART is ignored (assumed not set):
2030 * syscall won't restart (will return EINTR instead)
2031 * even after signal with SA_RESTART set.
2032 * However, after SIG_IGN or SIG_DFL signal it will.
2033 */
2034 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002035 break;
2036 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002037 /* Syscalls like nanosleep(), poll() which can't be
2038 * restarted with their original arguments use this
2039 * code. Kernel will execute restart_syscall() instead,
2040 * which changes arguments before restarting syscall.
2041 * SA_RESTART is ignored (assumed not set) similarly
2042 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2043 * since restart data is saved in "restart block"
2044 * in task struct, and if signal handler uses a syscall
2045 * which in turn saves another such restart block,
2046 * old data is lost and restart becomes impossible)
2047 */
2048 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002049 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002050 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002051 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002052 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002053 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002054 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002055 strerror(u_error));
2056 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002057 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002058 strerror(u_error));
2059 break;
2060 }
2061 if ((sys_res & RVAL_STR) && tcp->auxstr)
2062 tprintf(" (%s)", tcp->auxstr);
2063 }
2064 else {
2065 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002066 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002067 else {
2068 switch (sys_res & RVAL_MASK) {
2069 case RVAL_HEX:
2070 tprintf("= %#lx", tcp->u_rval);
2071 break;
2072 case RVAL_OCTAL:
2073 tprintf("= %#lo", tcp->u_rval);
2074 break;
2075 case RVAL_UDECIMAL:
2076 tprintf("= %lu", tcp->u_rval);
2077 break;
2078 case RVAL_DECIMAL:
2079 tprintf("= %ld", tcp->u_rval);
2080 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002081 default:
2082 fprintf(stderr,
2083 "invalid rval format\n");
2084 break;
2085 }
2086 }
2087 if ((sys_res & RVAL_STR) && tcp->auxstr)
2088 tprintf(" (%s)", tcp->auxstr);
2089 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002090 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002091 tv_sub(&tv, &tv, &tcp->etime);
2092 tprintf(" <%ld.%06ld>",
2093 (long) tv.tv_sec, (long) tv.tv_usec);
2094 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002095 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002096 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002097 line_ended();
2098
Denys Vlasenko3b738812011-08-22 02:06:35 +02002099 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002100 tcp->flags &= ~TCB_INSYSCALL;
2101 return 0;
2102}
2103
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002104int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002105trace_syscall(struct tcb *tcp)
2106{
2107 return exiting(tcp) ?
2108 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2109}