blob: cf9cd0820754e3885f2a826f662cbcae13c8c029 [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 Vlasenkoe4cc7c52012-03-23 11:29:01 +0100340 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000341 int i = string_to_uint(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;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000376
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100377 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000378 int signo = string_to_uint(s);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000379 if (signo < 0 || signo >= MAX_QUALS)
380 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000381 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000382 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000383 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000384 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000385 s += 3;
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100386 for (i = 0; i <= NSIG; i++) {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000387 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000388 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000389 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000390 }
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100391 }
Roland McGrath76421df2005-02-02 03:51:18 +0000392 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000393}
394
395static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000396qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000397{
398 return -1;
399}
400
401static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000402qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000403{
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100404 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000405 int desc = string_to_uint(s);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000406 if (desc < 0 || desc >= MAX_QUALS)
407 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000408 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000409 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000410 }
411 return -1;
412}
413
414static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000415lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000416{
417 if (strcmp(s, "file") == 0)
418 return TRACE_FILE;
419 if (strcmp(s, "ipc") == 0)
420 return TRACE_IPC;
421 if (strcmp(s, "network") == 0)
422 return TRACE_NETWORK;
423 if (strcmp(s, "process") == 0)
424 return TRACE_PROCESS;
425 if (strcmp(s, "signal") == 0)
426 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000427 if (strcmp(s, "desc") == 0)
428 return TRACE_DESC;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000429 return -1;
430}
431
432void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000433qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000434{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000435 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000436 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000437 char *copy;
438 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000439 int i, n;
440
441 opt = &qual_options[0];
442 for (i = 0; (p = qual_options[i].option_name); i++) {
443 n = strlen(p);
444 if (strncmp(s, p, n) == 0 && s[n] == '=') {
445 opt = &qual_options[i];
446 s += n + 1;
447 break;
448 }
449 }
450 not = 0;
451 if (*s == '!') {
452 not = 1;
453 s++;
454 }
455 if (strcmp(s, "none") == 0) {
456 not = 1 - not;
457 s = "all";
458 }
459 if (strcmp(s, "all") == 0) {
460 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000461 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000462 }
463 return;
464 }
465 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000466 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000467 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200468 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200469 if (!copy)
470 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000471 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000472 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000473 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000474 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000475 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000476
477#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000478 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000479 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000480 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100481#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000482
483#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000484 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000485 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000486 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100487#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000488
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000489 continue;
490 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000491 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100492 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000493 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000494 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000495 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000496 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000497 return;
498}
499
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000500#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000501static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000502decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000503{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000504 unsigned long addr;
505 unsigned int i, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000506
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000507 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
508 return;
509
510 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
511 addr = tcp->u_arg[1];
512 tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100513 size = current_wordsize;
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000514 for (i = 0; i < tcp->u_nargs; ++i) {
515 if (size == sizeof(int)) {
516 unsigned int arg;
517 if (umove(tcp, addr, &arg) < 0)
518 arg = 0;
519 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000520 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000521 else {
522 unsigned long arg;
523 if (umove(tcp, addr, &arg) < 0)
524 arg = 0;
525 tcp->u_arg[i] = arg;
526 }
527 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000528 }
529}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000530#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400531
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000532#ifdef SYS_ipc_subcall
533static void
534decode_ipc_subcall(struct tcb *tcp)
535{
536 unsigned int i;
537
538 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
539 return;
540
541 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
542 tcp->u_nargs = sysent[tcp->scno].nargs;
543 for (i = 0; i < tcp->u_nargs; i++)
544 tcp->u_arg[i] = tcp->u_arg[i + 1];
545}
546#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000547
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200548int
549printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000550{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200551 if (entering(tcp)) {
552 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000553
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200554 for (i = 0; i < tcp->u_nargs; i++)
555 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
556 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000557 return 0;
558}
559
Denys Vlasenko72879c62012-02-27 14:18:02 +0100560int
561printargs_lu(struct tcb *tcp)
562{
563 if (entering(tcp)) {
564 int i;
565
566 for (i = 0; i < tcp->u_nargs; i++)
567 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
568 }
569 return 0;
570}
571
572int
573printargs_ld(struct tcb *tcp)
574{
575 if (entering(tcp)) {
576 int i;
577
578 for (i = 0; i < tcp->u_nargs; i++)
579 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
580 }
581 return 0;
582}
583
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200584long
585getrval2(struct tcb *tcp)
586{
587 long val = -1;
588
Denys Vlasenko523635f2012-02-25 02:44:25 +0100589#if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200590 struct pt_regs regs;
591 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
592 return -1;
593 val = regs.u_regs[U_REG_O1];
594#elif defined(SH)
595 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
596 return -1;
597#elif defined(IA64)
598 if (upeek(tcp, PT_R9, &val) < 0)
599 return -1;
600#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200601
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200602 return val;
603}
604
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200605int
606is_restart_error(struct tcb *tcp)
607{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200608 switch (tcp->u_error) {
609 case ERESTARTSYS:
610 case ERESTARTNOINTR:
611 case ERESTARTNOHAND:
612 case ERESTART_RESTARTBLOCK:
613 return 1;
614 default:
615 break;
616 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200617 return 0;
618}
619
Denys Vlasenko523635f2012-02-25 02:44:25 +0100620#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100621struct pt_regs i386_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100622#elif defined(X86_64)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100623/*
624 * On 32 bits, pt_regs and user_regs_struct are the same,
625 * but on 64 bits, user_regs_struct has six more fields:
626 * fs_base, gs_base, ds, es, fs, gs.
627 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
628 */
629static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100630#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200631long r8, r10, psr; /* TODO: make static? */
632long ia32 = 0; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100633#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +0100634static long ppc_result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100635#elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200636static long d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100637#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200638static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100639#elif defined(ARM)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200640static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100641#elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200642static long r0;
643static long a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100644#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200645static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100646#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200647static struct pt_regs regs;
648static unsigned long trap;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100649#elif defined(LINUX_MIPSN32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200650static long long a3;
651static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100652#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200653static long a3;
654static long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100655#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200656static long gpr2;
657static long pc;
658static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100659#elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200660static long r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100661#elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200662static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100663#elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200664static long r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100665#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200666static long r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100667#elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200668static long r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100669#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000670
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200671/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100672 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
673 * 1: ok, continue in trace_syscall_entering().
674 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200675 * ("????" etc) and bail out.
676 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100677static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200678get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000679{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000680 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000681
Denys Vlasenko523635f2012-02-25 02:44:25 +0100682#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000683 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200684 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000685
686 if (syscall_mode != -ENOSYS) {
687 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000688 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000689 */
690 scno = syscall_mode;
691 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000692 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000693 * Old style of "passing" the scno via the SVC instruction.
694 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000695 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200696 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200697 static const int gpr_offset[16] = {
698 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
699 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
700 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
701 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
702 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000703
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000704 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000705 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000706 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000707 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000708 if (errno) {
709 perror("peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000710 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000711 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000712
713 /*
714 * We have to check if the SVC got executed directly or via an
715 * EXECUTE instruction. In case of EXECUTE it is necessary to do
716 * instruction decoding to derive the system call number.
717 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
718 * so that this doesn't work if a SVC opcode is part of an EXECUTE
719 * opcode. Since there is no way to find out the opcode size this
720 * is the best we can do...
721 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000722 if ((opcode & 0xff00) == 0x0a00) {
723 /* SVC opcode */
724 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000725 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000726 else {
727 /* SVC got executed by EXECUTE instruction */
728
729 /*
730 * Do instruction decoding of EXECUTE. If you really want to
731 * understand this, read the Principles of Operations.
732 */
733 svc_addr = (void *) (opcode & 0xfff);
734
735 tmp = 0;
736 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000737 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000738 return -1;
739 svc_addr += tmp;
740
741 tmp = 0;
742 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000743 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000744 return -1;
745 svc_addr += tmp;
746
Denys Vlasenkofb036672009-01-23 16:30:26 +0000747 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000748 if (errno)
749 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100750# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000751 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100752# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000753 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100754# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000755 tmp = 0;
756 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000757 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000758 return -1;
759
760 scno = (scno | tmp) & 0xff;
761 }
762 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100763#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000764 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000765 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100766# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200767 /* TODO: speed up strace by not doing this at every syscall.
768 * We only need to do it after execve.
769 */
770 int currpers;
771 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200772
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200773 /* Check for 64/32 bit mode. */
774 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
775 return -1;
776 /* SF is bit 0 of MSR */
777 if (val < 0)
778 currpers = 0;
779 else
780 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000781 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100782# endif
783#elif defined(AVR32)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200784 /* Read complete register set in one go. */
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000785 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
786 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200787 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100788#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000789 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +0000790 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100791#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200792 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000793 return -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200794 scno = i386_regs.orig_eax;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100795#elif defined(X86_64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200796 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200797 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
798 return -1;
799 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +0000800
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200801 /* Check CS register value. On x86-64 linux it is:
802 * 0x33 for long mode (64 bit)
803 * 0x23 for compatibility mode (32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200804 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200805 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200806 case 0x23: currpers = 1; break;
807 case 0x33: currpers = 0; break;
808 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200809 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200810 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200811 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200812 currpers = current_personality;
813 break;
814 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100815# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200816 /* This version analyzes the opcode of a syscall instruction.
817 * (int 0x80 on i386 vs. syscall on x86-64)
818 * It works, but is too complicated.
819 */
820 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +0000821
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200822 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +0000823
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200824 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
825 rip -= 2;
826 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +0000827
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200828 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200829 if (errno)
830 fprintf(stderr, "ptrace_peektext failed: %s\n",
831 strerror(errno));
832 switch (call & 0xffff) {
833 /* x86-64: syscall = 0x0f 0x05 */
834 case 0x050f: currpers = 0; break;
835 /* i386: int 0x80 = 0xcd 0x80 */
836 case 0x80cd: currpers = 1; break;
837 default:
838 currpers = current_personality;
839 fprintf(stderr,
840 "Unknown syscall opcode (0x%04X) while "
841 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200842 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200843 break;
844 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100845# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000846 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100847#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000848# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200849 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +0000850 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200851 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +0200852 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200853 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000854 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200855 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +0000856 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200857 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100858#elif defined(ARM)
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +0200859 /* Read complete register set in one go. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000860 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
Roland McGrath0f87c492003-06-03 23:29:04 +0000861 return -1;
862
863 /*
864 * We only need to grab the syscall number on syscall entry.
865 */
866 if (regs.ARM_ip == 0) {
867 /*
868 * Note: we only deal with only 32-bit CPUs here.
869 */
870 if (regs.ARM_cpsr & 0x20) {
871 /*
872 * Get the Thumb-mode system call number
873 */
874 scno = regs.ARM_r7;
875 } else {
876 /*
877 * Get the ARM-mode system call number
878 */
879 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000880 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +0000881 if (errno)
882 return -1;
883
Roland McGrathf691bd22006-04-25 07:34:41 +0000884 /* Handle the EABI syscall convention. We do not
885 bother converting structures between the two
886 ABIs, but basic functionality should work even
887 if strace and the traced program have different
888 ABIs. */
889 if (scno == 0xef000000) {
890 scno = regs.ARM_r7;
891 } else {
892 if ((scno & 0x0ff00000) != 0x0f900000) {
893 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
894 scno);
895 return -1;
896 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000897
Roland McGrathf691bd22006-04-25 07:34:41 +0000898 /*
899 * Fixup the syscall number
900 */
901 scno &= 0x000fffff;
902 }
Roland McGrath0f87c492003-06-03 23:29:04 +0000903 }
Roland McGrath56703312008-05-20 01:35:55 +0000904 if (scno & 0x0f0000) {
905 /*
906 * Handle ARM specific syscall
907 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000908 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +0000909 scno &= 0x0000ffff;
910 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000911 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +0000912
Roland McGrath0f87c492003-06-03 23:29:04 +0000913 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200914 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
915 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000916 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100917#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000918 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000919 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100920#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +0000921 unsigned long long regs[38];
922
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200923 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +0000924 return -1;
925 a3 = regs[REG_A3];
926 r2 = regs[REG_V0];
927
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200928 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200929 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200930 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100931 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200932 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000933 return 0;
934 }
Roland McGrath542c2c62008-05-20 01:11:56 +0000935 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100936#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000937 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000938 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200939 if (upeek(tcp, REG_V0, &scno) < 0)
940 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +0000941
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200942 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200943 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100944 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200945 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +0000946 return 0;
947 }
Wichert Akkermanf90da011999-10-31 21:15:38 +0000948 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100949#elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000950 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000951 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200952 if (upeek(tcp, REG_R0, &scno) < 0)
953 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000954
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200955 /*
956 * Do some sanity checks to figure out if it's
957 * really a syscall entry
958 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +0200959 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200960 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +0100961 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200962 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000963 return 0;
964 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000965 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100966#elif defined(SPARC) || defined(SPARC64)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000967 /* Everything we need is in the current register set. */
Denys Vlasenkofb036672009-01-23 16:30:26 +0000968 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000969 return -1;
970
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200971 /* Disassemble the syscall trap. */
972 /* Retrieve the syscall trap instruction. */
973 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100974# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200975 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
976 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100977# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200978 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100979# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200980 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +0000981 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200982
983 /* Disassemble the trap to see what personality to use. */
984 switch (trap) {
985 case 0x91d02010:
986 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000987 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200988 break;
989 case 0x91d0206d:
990 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000991 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200992 break;
993 case 0x91d02000:
994 /* SunOS syscall trap. (pers 1) */
995 fprintf(stderr, "syscall: SunOS no support\n");
996 return -1;
997 case 0x91d02008:
998 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000999 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001000 break;
1001 case 0x91d02009:
1002 /* NetBSD/FreeBSD syscall trap. */
1003 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1004 return -1;
1005 case 0x91d02027:
1006 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001007 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001008 break;
1009 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001010# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001011 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001012# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001013 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001014# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001015 return -1;
1016 }
1017
1018 /* Extract the system call number from the registers. */
1019 if (trap == 0x91d02027)
1020 scno = 156;
1021 else
1022 scno = regs.u_regs[U_REG_G1];
1023 if (scno == 0) {
1024 scno = regs.u_regs[U_REG_O0];
1025 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1026 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001027#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001028 if (upeek(tcp, PT_GR20, &scno) < 0)
1029 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001030#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001031 /*
1032 * In the new syscall ABI, the system call number is in R3.
1033 */
1034 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1035 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001036
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001037 if (scno < 0) {
1038 /* Odd as it may seem, a glibc bug has been known to cause
1039 glibc to issue bogus negative syscall numbers. So for
1040 our purposes, make strace print what it *should* have been */
1041 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001042 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001043 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001044 "Detected glibc bug: bogus system call"
1045 " number = %ld, correcting to %ld\n",
1046 scno,
1047 correct_scno);
1048 scno = correct_scno;
1049 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001050#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001051 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001052 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001053 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001054#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001055 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1056 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001057#elif defined(TILE)
Chris Metcalfc8c66982009-12-28 10:00:15 -05001058 if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1059 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001060#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001061 if (upeek(tcp, 0, &scno) < 0)
1062 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001063#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001064
Denys Vlasenko523635f2012-02-25 02:44:25 +01001065#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001066 /* new syscall ABI returns result in R0 */
1067 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1068 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001069#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001070 /* ABI defines result returned in r9 */
1071 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1072 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001073#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001074
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001075 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001076 return 1;
1077}
1078
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001079/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001080 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001081 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1082 * 1: ok, continue in trace_syscall_entering().
1083 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001084 * ("????" etc) and bail out.
1085 */
Roland McGratha4d48532005-06-08 20:45:28 +00001086static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001087syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001088{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001089 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001090#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001091 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001092 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001093 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1094 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001095 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001096#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001097 {
1098 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001099 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001100 rax = (int)rax; /* sign extend from 32 bits */
1101 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001102 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001103 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1104 return 0;
1105 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001106 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001107#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001108 /* TODO: we already fetched PT_GPR2 in get_scno
1109 * and stored it in syscall_mode, reuse it here
1110 * instead of re-fetching?
1111 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001112 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001113 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001114 if (syscall_mode != -ENOSYS)
1115 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001116 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001117 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001118 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001119 return 0;
1120 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001121#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001122 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001123 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001124 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001125 if (d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001126 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001127 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001128 return 0;
1129 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001130#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001131 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001132 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001133 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001134 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001135 if (ia32 && r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001136 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001137 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001138 return 0;
1139 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001140#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001141 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001142 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001143 if (r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001144 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001145 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001146 return 0;
1147 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001148#elif defined(MICROBLAZE)
1149 if (upeek(tcp, 3 * 4, &r3) < 0)
1150 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001151 if (r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001152 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001153 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001154 return 0;
1155 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001156#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001157 return 1;
1158}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001159
Denys Vlasenko146b9442012-03-18 22:10:48 +01001160static void
1161internal_fork(struct tcb *tcp)
1162{
1163#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1164# define ARG_FLAGS 1
1165#else
1166# define ARG_FLAGS 0
1167#endif
1168#ifndef CLONE_UNTRACED
1169# define CLONE_UNTRACED 0x00800000
1170#endif
1171 if ((ptrace_setoptions
1172 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1173 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1174 return;
1175
1176 if (!followfork)
1177 return;
1178
1179 if (entering(tcp)) {
1180 /*
1181 * We won't see the new child if clone is called with
1182 * CLONE_UNTRACED, so we keep the same logic with that option
1183 * and don't trace it.
1184 */
1185 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1186 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1187 return;
1188 setbpt(tcp);
1189 } else {
1190 if (tcp->flags & TCB_BPTSET)
1191 clearbpt(tcp);
1192 }
1193}
1194
1195#if defined(TCB_WAITEXECVE)
1196static void
1197internal_exec(struct tcb *tcp)
1198{
1199 /* Maybe we have post-execve SIGTRAP suppressed? */
1200 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1201 return; /* yes, no need to do anything */
1202
1203 if (exiting(tcp) && syserror(tcp))
1204 /* Error in execve, no post-execve SIGTRAP expected */
1205 tcp->flags &= ~TCB_WAITEXECVE;
1206 else
1207 tcp->flags |= TCB_WAITEXECVE;
1208}
1209#endif
1210
1211static void
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001212internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001213{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001214 /*
1215 * We must always trace a few critical system calls in order to
1216 * correctly support following forks in the presence of tracing
1217 * qualifiers.
1218 */
1219 int (*func)();
1220
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001221 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001222 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001223
1224 func = sysent[tcp->scno].sys_func;
1225
1226 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001227 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001228 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001229 ) {
1230 internal_fork(tcp);
1231 return;
1232 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001233
Denys Vlasenko84703742012-02-25 02:38:52 +01001234#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001235 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001236# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001237 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001238# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001239 ) {
1240 internal_exec(tcp);
1241 return;
1242 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001243#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001244}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001245
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001246/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001247static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001248get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001249{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001250 int i, nargs;
1251
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001252 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001253 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001254 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001255 nargs = tcp->u_nargs = MAX_ARGS;
1256
Denys Vlasenko523635f2012-02-25 02:44:25 +01001257#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001258 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001259 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1260 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001261#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001262 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001263 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1264 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001265#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001266 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001267 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001268 long rbs_end;
1269 /* be backwards compatible with kernel < 2.4.4... */
1270# ifndef PT_RBS_END
1271# define PT_RBS_END PT_AR_BSP
1272# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001273
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001274 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1275 return -1;
1276 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001277 return -1;
1278
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001279 sof = (cfm >> 0) & 0x7f;
1280 sol = (cfm >> 7) & 0x7f;
1281 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1282
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001283 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001284 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1285 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1286 return -1;
1287 }
1288 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001289 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1290 PT_R9 /* ECX = out1 */,
1291 PT_R10 /* EDX = out2 */,
1292 PT_R14 /* ESI = out3 */,
1293 PT_R15 /* EDI = out4 */,
1294 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001295
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001296 for (i = 0; i < nargs; ++i) {
1297 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1298 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001299 /* truncate away IVE sign-extension */
1300 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001301 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001302 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001303#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001304 /* N32 and N64 both use up to six registers. */
1305 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001306
1307 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1308 return -1;
1309
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001310 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001311 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001312# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001313 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001314# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001315 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001316#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001317 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001318 long sp;
1319
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001320 if (upeek(tcp, REG_SP, &sp) < 0)
1321 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001322 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001323 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1324 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001325 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001326 (char *)(tcp->u_arg + 4));
1327 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001328 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001329 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001330 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001331 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001332#elif defined(POWERPC)
1333# ifndef PT_ORIG_R3
1334# define PT_ORIG_R3 34
1335# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001336 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001337 if (upeek(tcp, (i==0) ?
1338 (sizeof(unsigned long) * PT_ORIG_R3) :
1339 ((i+PT_R3) * sizeof(unsigned long)),
1340 &tcp->u_arg[i]) < 0)
1341 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001342 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001343#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001344 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001345 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001346#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001347 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001348 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1349 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001350#elif defined(ARM)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001351 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001352 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001353#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001354 (void)i;
1355 (void)nargs;
1356 tcp->u_arg[0] = regs.r12;
1357 tcp->u_arg[1] = regs.r11;
1358 tcp->u_arg[2] = regs.r10;
1359 tcp->u_arg[3] = regs.r9;
1360 tcp->u_arg[4] = regs.r5;
1361 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001362#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001363 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 +02001364
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001365 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001366 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1367 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001368#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001369 static const int syscall_regs[MAX_ARGS] = {
1370 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1371 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001372 };
1373
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001374 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001375 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001376 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001377#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001378 int i;
1379 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001380 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001381
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001382 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001383 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1384 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001385#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001386 (void)i;
1387 (void)nargs;
1388 if (current_personality == 0) { /* x86-64 ABI */
1389 tcp->u_arg[0] = x86_64_regs.rdi;
1390 tcp->u_arg[1] = x86_64_regs.rsi;
1391 tcp->u_arg[2] = x86_64_regs.rdx;
1392 tcp->u_arg[3] = x86_64_regs.r10;
1393 tcp->u_arg[4] = x86_64_regs.r8;
1394 tcp->u_arg[5] = x86_64_regs.r9;
1395 } else { /* i386 ABI */
1396 /* Sign-extend lower 32 bits */
1397 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1398 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1399 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1400 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1401 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1402 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1403 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001404#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001405 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001406 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1407 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001408#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001409 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001410 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001411 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001412 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001413
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001414 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001415 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1416 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001417#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001418 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001419 if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1420 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001421#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001422 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001423 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1424 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001425#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001426 (void)i;
1427 (void)nargs;
1428 tcp->u_arg[0] = i386_regs.ebx;
1429 tcp->u_arg[1] = i386_regs.ecx;
1430 tcp->u_arg[2] = i386_regs.edx;
1431 tcp->u_arg[3] = i386_regs.esi;
1432 tcp->u_arg[4] = i386_regs.edi;
1433 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001434#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001435 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001436 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1437 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001438#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001439 return 1;
1440}
1441
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001442static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001443trace_syscall_entering(struct tcb *tcp)
1444{
1445 int res, scno_good;
1446
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001447#if defined TCB_WAITEXECVE
1448 if (tcp->flags & TCB_WAITEXECVE) {
1449 /* This is the post-execve SIGTRAP. */
1450 tcp->flags &= ~TCB_WAITEXECVE;
1451 return 0;
1452 }
1453#endif
1454
Denys Vlasenko06602d92011-08-24 17:53:52 +02001455 scno_good = res = get_scno(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001456 if (res == 0)
1457 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001458 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001459 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001460 if (res == 0)
1461 return res;
1462 if (res == 1)
1463 res = get_syscall_args(tcp);
1464 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001465
1466 if (res != 1) {
1467 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001468 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001469 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001470 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001471 tprintf("syscall_%lu(", tcp->scno);
1472 else
1473 tprintf("%s(", sysent[tcp->scno].sys_name);
1474 /*
1475 * " <unavailable>" will be added later by the code which
1476 * detects ptrace errors.
1477 */
1478 goto ret;
1479 }
1480
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001481#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1482 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001483# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001484 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001485 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001486 break;
1487 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001488# endif
1489# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001490 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001491 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001492 break;
1493 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001494# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001495 break;
1496 }
1497#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1498
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001499 internal_syscall(tcp);
1500
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001501 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001502 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1503 (tracing_paths && !pathtrace_match(tcp))) {
1504 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1505 return 0;
1506 }
1507
1508 tcp->flags &= ~TCB_FILTERED;
1509
1510 if (cflag == CFLAG_ONLY_STATS) {
1511 res = 0;
1512 goto ret;
1513 }
1514
1515 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001516 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001517 tprintf("syscall_%lu(", tcp->scno);
1518 else
1519 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001520 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001521 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1522 sysent[tcp->scno].sys_func != sys_exit))
1523 res = printargs(tcp);
1524 else
1525 res = (*sysent[tcp->scno].sys_func)(tcp);
1526
1527 if (fflush(tcp->outf) == EOF)
1528 return -1;
1529 ret:
1530 tcp->flags |= TCB_INSYSCALL;
1531 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001532 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001533 gettimeofday(&tcp->etime, NULL);
1534 return res;
1535}
1536
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001537/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001538 * 1: ok, continue in trace_syscall_exiting().
1539 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001540 * ("????" etc) and bail out.
1541 */
1542static int
1543get_syscall_result(struct tcb *tcp)
1544{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001545#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001546 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1547 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001548#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001549# define SO_MASK 0x10000000
1550 {
1551 long flags;
1552 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1553 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001554 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001555 return -1;
1556 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001557 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001558 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001559#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001560 /* Read complete register set in one go. */
1561 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1562 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001563#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001564 if (upeek(tcp, PT_R0, &r0) < 0)
1565 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001566#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001567 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001568 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001569#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001570 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001571 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001572#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001573# define IA64_PSR_IS ((long)1 << 34)
1574 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1575 ia32 = (psr & IA64_PSR_IS) != 0;
1576 if (upeek(tcp, PT_R8, &r8) < 0)
1577 return -1;
1578 if (upeek(tcp, PT_R10, &r10) < 0)
1579 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001580#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001581 /* Read complete register set in one go. */
1582 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1583 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001584#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001585 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1586 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001587#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001588 unsigned long long regs[38];
1589
1590 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1591 return -1;
1592 a3 = regs[REG_A3];
1593 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001594#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001595 if (upeek(tcp, REG_A3, &a3) < 0)
1596 return -1;
1597 if (upeek(tcp, REG_V0, &r2) < 0)
1598 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001599#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001600 if (upeek(tcp, REG_A3, &a3) < 0)
1601 return -1;
1602 if (upeek(tcp, REG_R0, &r0) < 0)
1603 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001604#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001605 /* Everything we need is in the current register set. */
1606 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1607 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001608#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001609 if (upeek(tcp, PT_GR28, &r28) < 0)
1610 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001611#elif defined(SH)
1612#elif defined(SH64)
1613#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001614 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1615 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001616#elif defined(TILE)
1617#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001618 if (upeek(tcp, 3 * 4, &r3) < 0)
1619 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001620#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001621
Denys Vlasenko523635f2012-02-25 02:44:25 +01001622#if defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001623 /* new syscall ABI returns result in R0 */
1624 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1625 return -1;
1626#elif defined(SH64)
1627 /* ABI defines result returned in r9 */
1628 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1629 return -1;
1630#endif
1631
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001632 return 1;
1633}
1634
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001635/* Called at each syscall exit */
1636static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001637syscall_fixup_on_sysexit(struct tcb *tcp)
1638{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001639#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001640 if (syscall_mode != -ENOSYS)
1641 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001642 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001643 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1644 /*
1645 * Return from execve.
1646 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1647 * flag set for the post-execve SIGTRAP to see and reset.
1648 */
1649 gpr2 = 0;
1650 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001651#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001652}
1653
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001654/*
1655 * Check the syscall return value register value for whether it is
1656 * a negated errno code indicating an error, or a success return value.
1657 */
1658static inline int
1659is_negated_errno(unsigned long int val)
1660{
1661 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001662#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001663 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001664 val = (unsigned int) val;
1665 max = (unsigned int) max;
1666 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001667#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001668 return val > max;
1669}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001670
Denys Vlasenko907735a2012-03-21 00:23:16 +01001671/* Returns:
1672 * 1: ok, continue in trace_syscall_exiting().
1673 * -1: error, trace_syscall_exiting() should print error indicator
1674 * ("????" etc) and bail out.
1675 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001676static int
1677get_error(struct tcb *tcp)
1678{
1679 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001680 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001681 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001682 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1683 check_errno = 0;
1684 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001685#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001686 if (check_errno && is_negated_errno(gpr2)) {
1687 tcp->u_rval = -1;
1688 u_error = -gpr2;
1689 }
1690 else {
1691 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001692 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001693#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001694 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001695 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001696 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001697 }
1698 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001699 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001700 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001701#elif defined(X86_64)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001702 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001703 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001704 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001705 }
1706 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001707 tcp->u_rval = x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001708 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001709#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001710 if (ia32) {
1711 int err;
1712
1713 err = (int)r8;
1714 if (check_errno && is_negated_errno(err)) {
1715 tcp->u_rval = -1;
1716 u_error = -err;
1717 }
1718 else {
1719 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001720 }
1721 } else {
1722 if (check_errno && r10) {
1723 tcp->u_rval = -1;
1724 u_error = r8;
1725 } else {
1726 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001727 }
1728 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001729#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001730 if (check_errno && a3) {
1731 tcp->u_rval = -1;
1732 u_error = r2;
1733 } else {
1734 tcp->u_rval = r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001735 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001736#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001737 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001738 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001739 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001740 }
1741 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001742 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001743 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001744#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001745 if (check_errno && is_negated_errno(d0)) {
1746 tcp->u_rval = -1;
1747 u_error = -d0;
1748 }
1749 else {
1750 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001751 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001752#elif defined(ARM)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001753 if (check_errno && is_negated_errno(regs.ARM_r0)) {
1754 tcp->u_rval = -1;
1755 u_error = -regs.ARM_r0;
1756 }
1757 else {
1758 tcp->u_rval = regs.ARM_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001759 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001760#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001761 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1762 tcp->u_rval = -1;
1763 u_error = -regs.r12;
1764 }
1765 else {
1766 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001767 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001768#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001769 if (check_errno && is_negated_errno(r0)) {
1770 tcp->u_rval = -1;
1771 u_error = -r0;
1772 } else {
1773 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001774 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001775#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001776 if (check_errno && a3) {
1777 tcp->u_rval = -1;
1778 u_error = r0;
1779 }
1780 else {
1781 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001782 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001783#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001784 if (check_errno && regs.psr & PSR_C) {
1785 tcp->u_rval = -1;
1786 u_error = regs.u_regs[U_REG_O0];
1787 }
1788 else {
1789 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001790 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001791#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001792 if (check_errno && regs.tstate & 0x1100000000UL) {
1793 tcp->u_rval = -1;
1794 u_error = regs.u_regs[U_REG_O0];
1795 }
1796 else {
1797 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001798 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001799#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001800 if (check_errno && is_negated_errno(r28)) {
1801 tcp->u_rval = -1;
1802 u_error = -r28;
1803 }
1804 else {
1805 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001806 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001807#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001808 if (check_errno && is_negated_errno(r0)) {
1809 tcp->u_rval = -1;
1810 u_error = -r0;
1811 }
1812 else {
1813 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001814 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001815#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001816 if (check_errno && is_negated_errno(r9)) {
1817 tcp->u_rval = -1;
1818 u_error = -r9;
1819 }
1820 else {
1821 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001822 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001823#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001824 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1825 tcp->u_rval = -1;
1826 u_error = -r10;
1827 }
1828 else {
1829 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001830 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001831#elif defined(TILE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001832 long rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001833 if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1834 return -1;
1835 if (check_errno && rval < 0 && rval > -nerrnos) {
1836 tcp->u_rval = -1;
1837 u_error = -rval;
1838 }
1839 else {
1840 tcp->u_rval = rval;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001841 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001842#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001843 if (check_errno && is_negated_errno(r3)) {
1844 tcp->u_rval = -1;
1845 u_error = -r3;
1846 }
1847 else {
1848 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001849 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001850#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001851 tcp->u_error = u_error;
1852 return 1;
1853}
1854
1855static void
1856dumpio(struct tcb *tcp)
1857{
1858 if (syserror(tcp))
1859 return;
1860 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1861 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001862 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001863 return;
1864 if (sysent[tcp->scno].sys_func == printargs)
1865 return;
1866 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1867 if (sysent[tcp->scno].sys_func == sys_read ||
1868 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001869 sysent[tcp->scno].sys_func == sys_recv ||
1870 sysent[tcp->scno].sys_func == sys_recvfrom)
1871 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1872 else if (sysent[tcp->scno].sys_func == sys_readv)
1873 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1874 return;
1875 }
1876 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1877 if (sysent[tcp->scno].sys_func == sys_write ||
1878 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001879 sysent[tcp->scno].sys_func == sys_send ||
1880 sysent[tcp->scno].sys_func == sys_sendto)
1881 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1882 else if (sysent[tcp->scno].sys_func == sys_writev)
1883 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1884 return;
1885 }
1886}
1887
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001888static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001889trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001890{
1891 int sys_res;
1892 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001893 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001894 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001895
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001896 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001897 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001898 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00001899
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001900#if SUPPORTED_PERSONALITIES > 1
1901 update_personality(tcp, tcp->currpers);
1902#endif
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02001903 res = get_syscall_result(tcp);
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001904 if (res == 1) {
1905 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01001906 res = get_error(tcp); /* returns 1 or -1 */
1907 if (res == 1) {
1908 internal_syscall(tcp);
1909 if (filtered(tcp)) {
1910 goto ret;
1911 }
1912 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00001913 }
1914
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001915 if (cflag) {
1916 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02001917 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02001918 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001919 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001920 }
1921 }
1922
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01001923 /* If not in -ff mode, and printing_tcp != tcp,
1924 * then the log currently does not end with output
1925 * of _our syscall entry_, but with something else.
1926 * We need to say which syscall's return is this.
1927 *
1928 * Forced reprinting via TCB_REPRINT is used only by
1929 * "strace -ff -oLOG test/threaded_execve" corner case.
1930 * It's the only case when -ff mode needs reprinting.
1931 */
1932 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
1933 tcp->flags &= ~TCB_REPRINT;
1934 printleader(tcp);
1935 if (!SCNO_IN_RANGE(tcp->scno))
1936 tprintf("<... syscall_%lu resumed> ", tcp->scno);
1937 else
1938 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
1939 }
1940 printing_tcp = tcp;
1941
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001942 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01001943 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001944 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001945 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01001946 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001947 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001948 tcp->flags &= ~TCB_INSYSCALL;
1949 return res;
1950 }
1951
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01001952 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001953 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001954 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01001955 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01001956 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02001957 /* FIXME: not_failing_only (IOW, option -z) is broken:
1958 * failure of syscall is known only after syscall return.
1959 * Thus we end up with something like this on, say, ENOENT:
1960 * open("doesnt_exist", O_RDONLY <unfinished ...>
1961 * {next syscall decode}
1962 * whereas the intended result is that open(...) line
1963 * is not shown at all.
1964 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001965 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02001966 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001967 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
1968 }
1969
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02001970 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02001971 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02001972 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001973 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001974 qual_flags[tcp->scno] & QUAL_RAW) {
1975 if (u_error)
1976 tprintf("= -1 (errno %ld)", u_error);
1977 else
1978 tprintf("= %#lx", tcp->u_rval);
1979 }
1980 else if (!(sys_res & RVAL_NONE) && u_error) {
1981 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01001982 /* Blocked signals do not interrupt any syscalls.
1983 * In this case syscalls don't return ERESTARTfoo codes.
1984 *
1985 * Deadly signals set to SIG_DFL interrupt syscalls
1986 * and kill the process regardless of which of the codes below
1987 * is returned by the interrupted syscall.
1988 * In some cases, kernel forces a kernel-generated deadly
1989 * signal to be unblocked and set to SIG_DFL (and thus cause
1990 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
1991 * or SIGILL. (The alternative is to leave process spinning
1992 * forever on the faulty instruction - not useful).
1993 *
1994 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
1995 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
1996 * but kernel will always restart them.
1997 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001998 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01001999 /* Most common type of signal-interrupted syscall exit code.
2000 * The system call will be restarted with the same arguments
2001 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2002 */
2003 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002004 break;
2005 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002006 /* Rare. For example, fork() returns this if interrupted.
2007 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2008 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002009 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002010 break;
2011 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002012 /* pause(), rt_sigsuspend() etc use this code.
2013 * SA_RESTART is ignored (assumed not set):
2014 * syscall won't restart (will return EINTR instead)
2015 * even after signal with SA_RESTART set.
2016 * However, after SIG_IGN or SIG_DFL signal it will.
2017 */
2018 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002019 break;
2020 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002021 /* Syscalls like nanosleep(), poll() which can't be
2022 * restarted with their original arguments use this
2023 * code. Kernel will execute restart_syscall() instead,
2024 * which changes arguments before restarting syscall.
2025 * SA_RESTART is ignored (assumed not set) similarly
2026 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2027 * since restart data is saved in "restart block"
2028 * in task struct, and if signal handler uses a syscall
2029 * which in turn saves another such restart block,
2030 * old data is lost and restart becomes impossible)
2031 */
2032 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002033 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002034 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002035 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002036 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002037 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002038 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002039 strerror(u_error));
2040 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002041 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002042 strerror(u_error));
2043 break;
2044 }
2045 if ((sys_res & RVAL_STR) && tcp->auxstr)
2046 tprintf(" (%s)", tcp->auxstr);
2047 }
2048 else {
2049 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002050 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002051 else {
2052 switch (sys_res & RVAL_MASK) {
2053 case RVAL_HEX:
2054 tprintf("= %#lx", tcp->u_rval);
2055 break;
2056 case RVAL_OCTAL:
2057 tprintf("= %#lo", tcp->u_rval);
2058 break;
2059 case RVAL_UDECIMAL:
2060 tprintf("= %lu", tcp->u_rval);
2061 break;
2062 case RVAL_DECIMAL:
2063 tprintf("= %ld", tcp->u_rval);
2064 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002065 default:
2066 fprintf(stderr,
2067 "invalid rval format\n");
2068 break;
2069 }
2070 }
2071 if ((sys_res & RVAL_STR) && tcp->auxstr)
2072 tprintf(" (%s)", tcp->auxstr);
2073 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002074 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002075 tv_sub(&tv, &tv, &tcp->etime);
2076 tprintf(" <%ld.%06ld>",
2077 (long) tv.tv_sec, (long) tv.tv_usec);
2078 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002079 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002080 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002081 line_ended();
2082
Denys Vlasenko3b738812011-08-22 02:06:35 +02002083 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002084 tcp->flags &= ~TCB_INSYSCALL;
2085 return 0;
2086}
2087
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002088int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002089trace_syscall(struct tcb *tcp)
2090{
2091 return exiting(tcp) ?
2092 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2093}