blob: 26c84deb905ec706fd9d3f0633a49317521f438e [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
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +010068#if defined(X86_64) || defined(X32)
69# include <linux/ptrace.h>
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +010070# include <sys/uio.h>
71# include <elf.h>
72#endif
73
Steve McIntyred8d3bd32012-10-24 17:58:16 +010074#if defined(AARCH64)
75# include <asm/ptrace.h>
76# include <sys/uio.h>
77# include <elf.h>
78#endif
79
Christian Svensson492f81f2013-02-14 13:26:27 +010080#if defined(OR1K)
81# include <sys/uio.h>
82# include <elf.h>
83#endif
84
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000085#ifndef ERESTARTSYS
Denys Vlasenko523635f2012-02-25 02:44:25 +010086# define ERESTARTSYS 512
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000087#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010088#ifndef ERESTARTNOINTR
Denys Vlasenko523635f2012-02-25 02:44:25 +010089# define ERESTARTNOINTR 513
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000090#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010091#ifndef ERESTARTNOHAND
92# define ERESTARTNOHAND 514 /* restart if no handler */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000093#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010094#ifndef ERESTART_RESTARTBLOCK
Denys Vlasenko523635f2012-02-25 02:44:25 +010095# define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
Roland McGrath9c555e72003-07-09 09:47:59 +000096#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010097
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000098#ifndef NSIG
Denys Vlasenko523635f2012-02-25 02:44:25 +010099# warning: NSIG is not defined, using 32
100# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000101#endif
102#ifdef ARM
Denys Vlasenko041b3ee2011-08-18 12:48:56 +0200103/* Ugh. Is this really correct? ARM has no RT signals?! */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100104# undef NSIG
105# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000106#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000107
108#include "syscall.h"
109
110/* Define these shorthand notations to simplify the syscallent files. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000111#define TD TRACE_DESC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000112#define TF TRACE_FILE
113#define TI TRACE_IPC
114#define TN TRACE_NETWORK
115#define TP TRACE_PROCESS
116#define TS TRACE_SIGNAL
Namhyung Kim96792962012-10-24 11:41:57 +0900117#define TM TRACE_MEMORY
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000118#define NF SYSCALL_NEVER_FAILS
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200119#define MA MAX_ARGS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000120
Roland McGrathee36ce12004-09-04 03:53:10 +0000121static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122#include "syscallent.h"
123};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000124
125#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000126static const struct sysent sysent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100127# include "syscallent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000128};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200129#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000130
131#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000132static const struct sysent sysent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100133# include "syscallent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000134};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200135#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000136
137/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000138#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000139#undef TF
140#undef TI
141#undef TN
142#undef TP
143#undef TS
Namhyung Kim96792962012-10-24 11:41:57 +0900144#undef TM
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000145#undef NF
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200146#undef MA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000147
Denys Vlasenko39fca622011-08-20 02:12:33 +0200148/*
149 * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
150 * program `ioctlsort', such that the list is sorted by the `code' field.
151 * This has the side-effect of resolving the _IO.. macros into
152 * plain integers, eliminating the need to include here everything
153 * in "/usr/include".
154 */
155
Roland McGrathee36ce12004-09-04 03:53:10 +0000156static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000157#include "errnoent.h"
158};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200159static const char *const signalent0[] = {
160#include "signalent.h"
161};
162static const struct ioctlent ioctlent0[] = {
163#include "ioctlent.h"
164};
165enum { nsyscalls0 = ARRAY_SIZE(sysent0) };
166enum { nerrnos0 = ARRAY_SIZE(errnoent0) };
167enum { nsignals0 = ARRAY_SIZE(signalent0) };
168enum { nioctlents0 = ARRAY_SIZE(ioctlent0) };
169int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000170
171#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000172static const char *const errnoent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100173# include "errnoent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000174};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200175static const char *const signalent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100176# include "signalent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200177};
178static const struct ioctlent ioctlent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100179# include "ioctlent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200180};
181enum { nsyscalls1 = ARRAY_SIZE(sysent1) };
182enum { nerrnos1 = ARRAY_SIZE(errnoent1) };
183enum { nsignals1 = ARRAY_SIZE(signalent1) };
184enum { nioctlents1 = ARRAY_SIZE(ioctlent1) };
185int qual_flags1[MAX_QUALS];
186#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000187
188#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000189static const char *const errnoent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100190# include "errnoent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000191};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200192static const char *const signalent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100193# include "signalent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200194};
195static const struct ioctlent ioctlent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100196# include "ioctlent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200197};
198enum { nsyscalls2 = ARRAY_SIZE(sysent2) };
199enum { nerrnos2 = ARRAY_SIZE(errnoent2) };
200enum { nsignals2 = ARRAY_SIZE(signalent2) };
201enum { nioctlents2 = ARRAY_SIZE(ioctlent2) };
202int qual_flags2[MAX_QUALS];
203#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000204
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100205const struct sysent *sysent = sysent0;
206const char *const *errnoent = errnoent0;
207const char *const *signalent = signalent0;
208const struct ioctlent *ioctlent = ioctlent0;
209unsigned nsyscalls = nsyscalls0;
210unsigned nerrnos = nerrnos0;
211unsigned nsignals = nsignals0;
212unsigned nioctlents = nioctlents0;
213int *qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000214
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100215#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenkoae8643e2013-02-15 14:55:14 +0100216unsigned current_personality;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000217
Denys Vlasenkoae8643e2013-02-15 14:55:14 +0100218# ifndef current_wordsize
219unsigned current_wordsize;
220static const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000221 PERSONALITY0_WORDSIZE,
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000222 PERSONALITY1_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100223# if SUPPORTED_PERSONALITIES > 2
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000224 PERSONALITY2_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100225# endif
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200226};
Denys Vlasenkoae8643e2013-02-15 14:55:14 +0100227# endif
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000228
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200229void
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000230set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000231{
232 switch (personality) {
233 case 0:
234 errnoent = errnoent0;
235 nerrnos = nerrnos0;
236 sysent = sysent0;
237 nsyscalls = nsyscalls0;
238 ioctlent = ioctlent0;
239 nioctlents = nioctlents0;
240 signalent = signalent0;
241 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000242 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000243 break;
244
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000245 case 1:
246 errnoent = errnoent1;
247 nerrnos = nerrnos1;
248 sysent = sysent1;
249 nsyscalls = nsyscalls1;
250 ioctlent = ioctlent1;
251 nioctlents = nioctlents1;
252 signalent = signalent1;
253 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000254 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000255 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000256
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100257# if SUPPORTED_PERSONALITIES >= 3
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000258 case 2:
259 errnoent = errnoent2;
260 nerrnos = nerrnos2;
261 sysent = sysent2;
262 nsyscalls = nsyscalls2;
263 ioctlent = ioctlent2;
264 nioctlents = nioctlents2;
265 signalent = signalent2;
266 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000267 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000268 break;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100269# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000270 }
271
272 current_personality = personality;
Denys Vlasenkoae8643e2013-02-15 14:55:14 +0100273# ifndef current_wordsize
274 current_wordsize = personality_wordsize[personality];
275# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000276}
277
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000278static void
279update_personality(struct tcb *tcp, int personality)
280{
281 if (personality == current_personality)
282 return;
283 set_personality(personality);
284
285 if (personality == tcp->currpers)
286 return;
287 tcp->currpers = personality;
288
H.J. Lu35be5812012-04-16 13:00:01 +0200289# if defined(POWERPC64)
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000290 if (!qflag) {
291 static const char *const names[] = {"64 bit", "32 bit"};
292 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
293 tcp->pid, names[personality]);
294 }
H.J. Lu35be5812012-04-16 13:00:01 +0200295# elif defined(X86_64)
296 if (!qflag) {
297 static const char *const names[] = {"64 bit", "32 bit", "x32"};
298 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
299 tcp->pid, names[personality]);
300 }
H.J. Lu085e4282012-04-17 11:05:04 -0700301# elif defined(X32)
302 if (!qflag) {
303 static const char *const names[] = {"x32", "32 bit"};
304 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
305 tcp->pid, names[personality]);
306 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000307# elif defined(AARCH64)
308 if (!qflag) {
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100309 static const char *const names[] = {"32-bit", "AArch64"};
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000310 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
311 tcp->pid, names[personality]);
312 }
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100313# elif defined(TILE)
314 if (!qflag) {
315 static const char *const names[] = {"64-bit", "32-bit"};
316 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
317 tcp->pid, names[personality]);
318 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100319# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000320}
321#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000322
Roland McGrath9797ceb2002-12-30 10:23:00 +0000323static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000324
Roland McGrathe10e62a2004-09-04 04:20:43 +0000325static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000326 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000327 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000328 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000329 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000330} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000331 { QUAL_TRACE, "trace", qual_syscall, "system call" },
332 { QUAL_TRACE, "t", qual_syscall, "system call" },
333 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
334 { QUAL_ABBREV, "a", qual_syscall, "system call" },
335 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
336 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
337 { QUAL_RAW, "raw", qual_syscall, "system call" },
338 { QUAL_RAW, "x", qual_syscall, "system call" },
339 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
340 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
341 { QUAL_SIGNAL, "s", qual_signal, "signal" },
342 { QUAL_FAULT, "fault", qual_fault, "fault" },
343 { QUAL_FAULT, "faults", qual_fault, "fault" },
344 { QUAL_FAULT, "m", qual_fault, "fault" },
345 { QUAL_READ, "read", qual_desc, "descriptor" },
346 { QUAL_READ, "reads", qual_desc, "descriptor" },
347 { QUAL_READ, "r", qual_desc, "descriptor" },
348 { QUAL_WRITE, "write", qual_desc, "descriptor" },
349 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
350 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000351 { 0, NULL, NULL, NULL },
352};
353
Roland McGrath9797ceb2002-12-30 10:23:00 +0000354static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000355qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000356{
Roland McGrath138c6a32006-01-12 09:50:49 +0000357 if (pers == 0 || pers < 0) {
358 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000359 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000360 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000361 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000362 }
363
364#if SUPPORTED_PERSONALITIES >= 2
365 if (pers == 1 || pers < 0) {
366 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000367 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000368 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000369 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000370 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100371#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000372
373#if SUPPORTED_PERSONALITIES >= 3
374 if (pers == 2 || pers < 0) {
375 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000376 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000377 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000378 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000379 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100380#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000381}
382
383static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000384qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000385{
386 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000387 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000388
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100389 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000390 int i = string_to_uint(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000391 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000392 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000393 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000394 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000395 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000396 for (i = 0; i < nsyscalls0; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000397 if (sysent0[i].sys_name &&
398 strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000399 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000400 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000401 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000402
403#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000404 for (i = 0; i < nsyscalls1; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000405 if (sysent1[i].sys_name &&
406 strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000407 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000408 rc = 0;
409 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100410#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000411
412#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000413 for (i = 0; i < nsyscalls2; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000414 if (sysent2[i].sys_name &&
415 strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000416 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000417 rc = 0;
418 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100419#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000420
Roland McGrathfe6b3522005-02-02 04:40:11 +0000421 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000422}
423
424static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000425qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000426{
427 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000428
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100429 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000430 int signo = string_to_uint(s);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000431 if (signo < 0 || signo >= MAX_QUALS)
432 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000433 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000434 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000435 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000436 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000437 s += 3;
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100438 for (i = 0; i <= NSIG; i++) {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000439 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000440 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000441 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000442 }
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100443 }
Roland McGrath76421df2005-02-02 03:51:18 +0000444 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000445}
446
447static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000448qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000449{
450 return -1;
451}
452
453static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000454qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000455{
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100456 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000457 int desc = string_to_uint(s);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000458 if (desc < 0 || desc >= MAX_QUALS)
459 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000460 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000461 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000462 }
463 return -1;
464}
465
466static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000467lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000468{
469 if (strcmp(s, "file") == 0)
470 return TRACE_FILE;
471 if (strcmp(s, "ipc") == 0)
472 return TRACE_IPC;
473 if (strcmp(s, "network") == 0)
474 return TRACE_NETWORK;
475 if (strcmp(s, "process") == 0)
476 return TRACE_PROCESS;
477 if (strcmp(s, "signal") == 0)
478 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000479 if (strcmp(s, "desc") == 0)
480 return TRACE_DESC;
Namhyung Kim96792962012-10-24 11:41:57 +0900481 if (strcmp(s, "memory") == 0)
482 return TRACE_MEMORY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000483 return -1;
484}
485
486void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000487qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000488{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000489 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000490 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000491 char *copy;
492 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000493 int i, n;
494
495 opt = &qual_options[0];
496 for (i = 0; (p = qual_options[i].option_name); i++) {
497 n = strlen(p);
498 if (strncmp(s, p, n) == 0 && s[n] == '=') {
499 opt = &qual_options[i];
500 s += n + 1;
501 break;
502 }
503 }
504 not = 0;
505 if (*s == '!') {
506 not = 1;
507 s++;
508 }
509 if (strcmp(s, "none") == 0) {
510 not = 1 - not;
511 s = "all";
512 }
513 if (strcmp(s, "all") == 0) {
514 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000515 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000516 }
517 return;
518 }
519 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000520 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000521 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200522 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200523 if (!copy)
524 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000525 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000526 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000527 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000528 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000529 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000530
531#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000532 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000533 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000534 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100535#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000536
537#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000538 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000539 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000540 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100541#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000542
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000543 continue;
544 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000545 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100546 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000547 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000548 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000549 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000550 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000551 return;
552}
553
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000554#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000555static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000556decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000557{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000558 unsigned long addr;
559 unsigned int i, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000560
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000561 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
562 return;
563
564 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
565 addr = tcp->u_arg[1];
566 tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100567 size = current_wordsize;
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000568 for (i = 0; i < tcp->u_nargs; ++i) {
569 if (size == sizeof(int)) {
570 unsigned int arg;
571 if (umove(tcp, addr, &arg) < 0)
572 arg = 0;
573 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000574 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000575 else {
576 unsigned long arg;
577 if (umove(tcp, addr, &arg) < 0)
578 arg = 0;
579 tcp->u_arg[i] = arg;
580 }
581 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000582 }
583}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000584#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400585
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000586#ifdef SYS_ipc_subcall
587static void
588decode_ipc_subcall(struct tcb *tcp)
589{
590 unsigned int i;
591
592 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
593 return;
594
595 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
596 tcp->u_nargs = sysent[tcp->scno].nargs;
597 for (i = 0; i < tcp->u_nargs; i++)
598 tcp->u_arg[i] = tcp->u_arg[i + 1];
599}
600#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000601
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200602int
603printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000604{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200605 if (entering(tcp)) {
606 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000607
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200608 for (i = 0; i < tcp->u_nargs; i++)
609 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
610 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000611 return 0;
612}
613
Denys Vlasenko72879c62012-02-27 14:18:02 +0100614int
615printargs_lu(struct tcb *tcp)
616{
617 if (entering(tcp)) {
618 int i;
619
620 for (i = 0; i < tcp->u_nargs; i++)
621 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
622 }
623 return 0;
624}
625
626int
627printargs_ld(struct tcb *tcp)
628{
629 if (entering(tcp)) {
630 int i;
631
632 for (i = 0; i < tcp->u_nargs; i++)
633 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
634 }
635 return 0;
636}
637
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100638#if defined(SPARC) || defined(SPARC64) || defined(IA64) || defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200639long
640getrval2(struct tcb *tcp)
641{
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100642 long val;
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200643
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100644# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200645 val = regs.u_regs[U_REG_O1];
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100646# elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200647 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
648 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100649# elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200650 if (upeek(tcp, PT_R9, &val) < 0)
651 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100652# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200653
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200654 return val;
655}
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100656#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200657
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200658int
659is_restart_error(struct tcb *tcp)
660{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200661 switch (tcp->u_error) {
662 case ERESTARTSYS:
663 case ERESTARTNOINTR:
664 case ERESTARTNOHAND:
665 case ERESTART_RESTARTBLOCK:
666 return 1;
667 default:
668 break;
669 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200670 return 0;
671}
672
Denys Vlasenko523635f2012-02-25 02:44:25 +0100673#if defined(I386)
Denys Vlasenko2550d482013-02-15 21:04:28 +0100674struct user_regs_struct i386_regs;
H.J. Lu35be5812012-04-16 13:00:01 +0200675#elif defined(X86_64) || defined(X32)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100676/*
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100677 * On i386, pt_regs and user_regs_struct are the same,
678 * but on 64 bit x86, user_regs_struct has six more fields:
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100679 * fs_base, gs_base, ds, es, fs, gs.
680 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
681 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100682struct i386_user_regs_struct {
683 uint32_t ebx;
684 uint32_t ecx;
685 uint32_t edx;
686 uint32_t esi;
687 uint32_t edi;
688 uint32_t ebp;
689 uint32_t eax;
690 uint32_t xds;
691 uint32_t xes;
692 uint32_t xfs;
693 uint32_t xgs;
694 uint32_t orig_eax;
695 uint32_t eip;
696 uint32_t xcs;
697 uint32_t eflags;
698 uint32_t esp;
699 uint32_t xss;
700};
701static union {
702 struct user_regs_struct x86_64_r;
703 struct i386_user_regs_struct i386_r;
704} x86_regs_union;
705# define x86_64_regs x86_regs_union.x86_64_r
706# define i386_regs x86_regs_union.i386_r
707static struct iovec x86_io = {
708 .iov_base = &x86_regs_union
709};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100710#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200711long ia32 = 0; /* not static */
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100712static long ia64_r8, ia64_r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100713#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +0100714static long ppc_result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100715#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100716static long m68k_d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100717#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100718static long bfin_r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100719#elif defined(ARM)
Denys Vlasenko401374e2013-02-06 18:24:39 +0100720struct pt_regs arm_regs; /* not static */
Steve McIntyred8d3bd32012-10-24 17:58:16 +0100721#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100722static union {
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100723 struct user_pt_regs aarch64_r;
724 struct arm_pt_regs arm_r;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100725} arm_regs_union;
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100726# define aarch64_regs arm_regs_union.aarch64_r
727# define arm_regs arm_regs_union.arm_r
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100728static struct iovec aarch64_io = {
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100729 .iov_base = &arm_regs_union
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100730};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100731#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100732static long alpha_r0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100733static long alpha_a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100734#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200735static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100736#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100737struct pt_regs regs; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100738#elif defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100739static long long mips_a3;
740static long long mips_r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100741#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100742static long mips_a3;
743static long mips_r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100744#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200745static long gpr2;
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200746static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100747#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100748static long hppa_r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100749#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100750static long sh_r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100751#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100752static long sh64_r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100753#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100754static long cris_r10;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100755#elif defined(TILE)
756struct pt_regs tile_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100757#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100758static long microblaze_r3;
Christian Svensson492f81f2013-02-14 13:26:27 +0100759#elif defined(OR1K)
760static struct user_regs_struct or1k_regs;
761static struct iovec or1k_io = {
762 .iov_base = &or1k_regs
763};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100764#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000765
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100766void
767printcall(struct tcb *tcp)
768{
769#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
770 sizeof(long) == 8 ? "[????????????????] " : \
771 NULL /* crash */)
772 if (get_regs_error) {
773 PRINTBADPC;
774 return;
775 }
776#if defined(I386)
777 tprintf("[%08lx] ", i386_regs.eip);
778#elif defined(S390) || defined(S390X)
779 long psw;
780 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
781 PRINTBADPC;
782 return;
783 }
784# ifdef S390
785 tprintf("[%08lx] ", psw);
786# elif S390X
Dmitry V. Levinddba73e2013-02-05 19:01:58 +0000787 tprintf("[%016lx] ", psw);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100788# endif
789#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100790 if (x86_io.iov_len == sizeof(i386_regs)) {
791 tprintf("[%08x] ", (unsigned) i386_regs.eip);
792 } else {
793# if defined(X86_64)
794 tprintf("[%016lx] ", (unsigned long) x86_64_regs.rip);
795# elif defined(X32)
796 /* Note: this truncates 64-bit rip to 32 bits */
797 tprintf("[%08lx] ", (unsigned long) x86_64_regs.rip);
798# endif
799 }
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100800#elif defined(IA64)
801 long ip;
802
803 if (upeek(tcp, PT_B0, &ip) < 0) {
804 PRINTBADPC;
805 return;
806 }
807 tprintf("[%08lx] ", ip);
808#elif defined(POWERPC)
809 long pc;
810
811 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
812 PRINTBADPC;
813 return;
814 }
815# ifdef POWERPC64
816 tprintf("[%016lx] ", pc);
817# else
818 tprintf("[%08lx] ", pc);
819# endif
820#elif defined(M68K)
821 long pc;
822
823 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
824 tprints("[????????] ");
825 return;
826 }
827 tprintf("[%08lx] ", pc);
828#elif defined(ALPHA)
829 long pc;
830
831 if (upeek(tcp, REG_PC, &pc) < 0) {
832 tprints("[????????????????] ");
833 return;
834 }
835 tprintf("[%08lx] ", pc);
836#elif defined(SPARC)
837 tprintf("[%08lx] ", regs.pc);
838#elif defined(SPARC64)
839 tprintf("[%08lx] ", regs.tpc);
840#elif defined(HPPA)
841 long pc;
842
843 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
844 tprints("[????????] ");
845 return;
846 }
847 tprintf("[%08lx] ", pc);
848#elif defined(MIPS)
849 long pc;
850
851 if (upeek(tcp, REG_EPC, &pc) < 0) {
852 tprints("[????????] ");
853 return;
854 }
855 tprintf("[%08lx] ", pc);
856#elif defined(SH)
857 long pc;
858
859 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
860 tprints("[????????] ");
861 return;
862 }
863 tprintf("[%08lx] ", pc);
864#elif defined(SH64)
865 long pc;
866
867 if (upeek(tcp, REG_PC, &pc) < 0) {
868 tprints("[????????????????] ");
869 return;
870 }
871 tprintf("[%08lx] ", pc);
872#elif defined(ARM)
Denys Vlasenko401374e2013-02-06 18:24:39 +0100873 tprintf("[%08lx] ", arm_regs.ARM_pc);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100874#elif defined(AARCH64)
875 /* tprintf("[%016lx] ", aarch64_regs.regs[???]); */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100876#elif defined(AVR32)
877 tprintf("[%08lx] ", regs.pc);
878#elif defined(BFIN)
879 long pc;
880
881 if (upeek(tcp, PT_PC, &pc) < 0) {
882 PRINTBADPC;
883 return;
884 }
885 tprintf("[%08lx] ", pc);
886#elif defined(CRISV10)
887 long pc;
888
889 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
890 PRINTBADPC;
891 return;
892 }
893 tprintf("[%08lx] ", pc);
894#elif defined(CRISV32)
895 long pc;
896
897 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
898 PRINTBADPC;
899 return;
900 }
901 tprintf("[%08lx] ", pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100902#elif defined(TILE)
903# ifdef _LP64
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500904 tprintf("[%016lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100905# else
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500906 tprintf("[%08lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100907# endif
Christian Svensson492f81f2013-02-14 13:26:27 +0100908#elif defined(OR1K)
909 tprintf("[%08lx] ", or1k_regs.pc);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100910#endif /* architecture */
911}
912
913#ifndef get_regs
914long get_regs_error;
915void get_regs(pid_t pid)
916{
917# if defined(AVR32)
918 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
919# elif defined(I386)
920 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &i386_regs);
921# elif defined(X86_64) || defined(X32)
Denys Vlasenkoe3b248d2013-02-15 00:24:19 +0100922 /*
923 * PTRACE_GETREGSET was introduced in 2.6.33.
924 * Let's be paranoid and require a bit later kernel.
925 */
926 if (os_release >= KERNEL_VERSION(2,6,35)) {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100927 /*x86_io.iov_base = &x86_regs_union; - already is */
928 x86_io.iov_len = sizeof(x86_regs_union);
929 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (long) &x86_io);
930 } else {
931 /* Use old method, with heuristical detection of 32-bitness */
932 x86_io.iov_len = sizeof(x86_64_regs);
933 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &x86_64_regs);
934 if (!get_regs_error && x86_64_regs.cs == 0x23) {
935 x86_io.iov_len = sizeof(i386_regs);
936 /*
937 * The order is important: i386_regs and x86_64_regs
938 * are overlaid in memory!
939 */
940 i386_regs.ebx = x86_64_regs.rbx;
941 i386_regs.ecx = x86_64_regs.rcx;
942 i386_regs.edx = x86_64_regs.rdx;
943 i386_regs.esi = x86_64_regs.rsi;
944 i386_regs.edi = x86_64_regs.rdi;
945 i386_regs.ebp = x86_64_regs.rbp;
946 i386_regs.eax = x86_64_regs.rax;
947 /*i386_regs.xds = x86_64_regs.ds; unused by strace */
948 /*i386_regs.xes = x86_64_regs.es; ditto... */
949 /*i386_regs.xfs = x86_64_regs.fs;*/
950 /*i386_regs.xgs = x86_64_regs.gs;*/
951 i386_regs.orig_eax = x86_64_regs.orig_rax;
952 i386_regs.eip = x86_64_regs.rip;
953 /*i386_regs.xcs = x86_64_regs.cs;*/
954 /*i386_regs.eflags = x86_64_regs.eflags;*/
955 i386_regs.esp = x86_64_regs.rsp;
956 /*i386_regs.xss = x86_64_regs.ss;*/
957 }
958 }
Denys Vlasenko401374e2013-02-06 18:24:39 +0100959# elif defined(ARM)
960 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (void *)&arm_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100961# elif defined(AARCH64)
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100962 /*aarch64_io.iov_base = &arm_regs_union; - already is */
963 aarch64_io.iov_len = sizeof(arm_regs_union);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100964 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void *)&aarch64_io);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100965# if 0
966 /* Paranoia checks */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100967 if (get_regs_error)
968 return;
969 switch (aarch64_io.iov_len) {
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100970 case sizeof(aarch64_regs):
971 /* We are in 64-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100972 break;
973 case sizeof(arm_regs):
974 /* We are in 32-bit mode */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100975 break;
976 default:
977 get_regs_error = -1;
978 break;
979 }
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100980# endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100981# elif defined(SPARC) || defined(SPARC64)
982 get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&regs, 0);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100983# elif defined(TILE)
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500984 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &tile_regs);
Christian Svensson492f81f2013-02-14 13:26:27 +0100985# elif defined(OR1K)
986 or1k_io.iov_len = sizeof(or1k_regs);
987 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &or1k_io);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100988# endif
989}
990#endif
991
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200992/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100993 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
994 * 1: ok, continue in trace_syscall_entering().
995 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200996 * ("????" etc) and bail out.
997 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100998static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200999get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001000{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001001 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001002
Denys Vlasenko523635f2012-02-25 02:44:25 +01001003#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001004 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001005 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +00001006
1007 if (syscall_mode != -ENOSYS) {
1008 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001009 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +00001010 */
1011 scno = syscall_mode;
1012 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001013 /*
Michal Ludvig882eda82002-11-11 12:50:47 +00001014 * Old style of "passing" the scno via the SVC instruction.
1015 */
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001016 long psw;
Michal Ludvig882eda82002-11-11 12:50:47 +00001017 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001018 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +02001019 static const int gpr_offset[16] = {
1020 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
1021 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
1022 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
1023 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
1024 };
Roland McGrath761b5d72002-12-15 23:58:31 +00001025
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001026 if (upeek(tcp, PT_PSWADDR, &psw) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +00001027 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +00001028 errno = 0;
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001029 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(psw - sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +00001030 if (errno) {
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001031 perror_msg("%s", "peektext(psw-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +00001032 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +00001033 }
Michal Ludvig882eda82002-11-11 12:50:47 +00001034
1035 /*
1036 * We have to check if the SVC got executed directly or via an
1037 * EXECUTE instruction. In case of EXECUTE it is necessary to do
1038 * instruction decoding to derive the system call number.
1039 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
1040 * so that this doesn't work if a SVC opcode is part of an EXECUTE
1041 * opcode. Since there is no way to find out the opcode size this
1042 * is the best we can do...
1043 */
Michal Ludvig882eda82002-11-11 12:50:47 +00001044 if ((opcode & 0xff00) == 0x0a00) {
1045 /* SVC opcode */
1046 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +00001047 }
Michal Ludvig882eda82002-11-11 12:50:47 +00001048 else {
1049 /* SVC got executed by EXECUTE instruction */
1050
1051 /*
1052 * Do instruction decoding of EXECUTE. If you really want to
1053 * understand this, read the Principles of Operations.
1054 */
1055 svc_addr = (void *) (opcode & 0xfff);
1056
1057 tmp = 0;
1058 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001059 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001060 return -1;
1061 svc_addr += tmp;
1062
1063 tmp = 0;
1064 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001065 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001066 return -1;
1067 svc_addr += tmp;
1068
Denys Vlasenkofb036672009-01-23 16:30:26 +00001069 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +00001070 if (errno)
1071 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001072# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +00001073 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001074# else
Michal Ludvig882eda82002-11-11 12:50:47 +00001075 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001076# endif
Michal Ludvig882eda82002-11-11 12:50:47 +00001077 tmp = 0;
1078 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001079 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001080 return -1;
1081
1082 scno = (scno | tmp) & 0xff;
1083 }
1084 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001085#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001086 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001087 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001088# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001089 /* TODO: speed up strace by not doing this at every syscall.
1090 * We only need to do it after execve.
1091 */
1092 int currpers;
1093 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +02001094
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001095 /* Check for 64/32 bit mode. */
1096 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
1097 return -1;
1098 /* SF is bit 0 of MSR */
1099 if (val < 0)
1100 currpers = 0;
1101 else
1102 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001103 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001104# endif
1105#elif defined(AVR32)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001106 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001107#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001108 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001109 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001110#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001111 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +02001112#elif defined(X86_64) || defined(X32)
1113# ifndef __X32_SYSCALL_BIT
1114# define __X32_SYSCALL_BIT 0x40000000
1115# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001116 int currpers;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001117# if 1
1118 /* GETREGSET of NT_PRSTATUS tells us regset size,
1119 * which unambiguously detects i386.
1120 *
1121 * Linux kernel distinguishes x86-64 and x32 processes
1122 * solely by looking at __X32_SYSCALL_BIT:
1123 * arch/x86/include/asm/compat.h::is_x32_task():
1124 * if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)
1125 * return true;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001126 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001127 if (x86_io.iov_len == sizeof(i386_regs)) {
1128 scno = i386_regs.orig_eax;
1129 currpers = 1;
1130 } else {
1131 scno = x86_64_regs.orig_rax;
1132 currpers = 0;
1133 if (scno & __X32_SYSCALL_BIT) {
1134 scno -= __X32_SYSCALL_BIT;
1135 currpers = 2;
1136 }
1137 }
1138# elif 0
1139 /* cs = 0x33 for long mode (native 64 bit and x32)
1140 * cs = 0x23 for compatibility mode (32 bit)
1141 * ds = 0x2b for x32 mode (x86-64 in 32 bit)
1142 */
1143 scno = x86_64_regs.orig_rax;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001144 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001145 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +02001146 case 0x33:
1147 if (x86_64_regs.ds == 0x2b) {
1148 currpers = 2;
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001149 scno &= ~__X32_SYSCALL_BIT;
H.J. Lu35be5812012-04-16 13:00:01 +02001150 } else
1151 currpers = 0;
1152 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001153 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001154 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001155 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001156 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001157 currpers = current_personality;
1158 break;
1159 }
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001160# elif 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001161 /* This version analyzes the opcode of a syscall instruction.
1162 * (int 0x80 on i386 vs. syscall on x86-64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001163 * It works, but is too complicated, and strictly speaking, unreliable.
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001164 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001165 unsigned long call, rip = x86_64_regs.rip;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001166 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
1167 rip -= 2;
1168 errno = 0;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001169 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001170 if (errno)
1171 fprintf(stderr, "ptrace_peektext failed: %s\n",
1172 strerror(errno));
1173 switch (call & 0xffff) {
1174 /* x86-64: syscall = 0x0f 0x05 */
1175 case 0x050f: currpers = 0; break;
1176 /* i386: int 0x80 = 0xcd 0x80 */
1177 case 0x80cd: currpers = 1; break;
1178 default:
1179 currpers = current_personality;
1180 fprintf(stderr,
1181 "Unknown syscall opcode (0x%04X) while "
1182 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001183 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001184 break;
1185 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001186# endif
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001187
H.J. Lu35be5812012-04-16 13:00:01 +02001188# ifdef X32
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001189 /* If we are built for a x32 system, then personality 0 is x32
1190 * (not x86_64), and stracing of x86_64 apps is not supported.
1191 * Stracing of i386 apps is still supported.
H.J. Lu085e4282012-04-17 11:05:04 -07001192 */
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001193 if (currpers == 0) {
1194 fprintf(stderr, "syscall_%lu(...) in unsupported "
1195 "64-bit mode of process PID=%d\n",
1196 scno, tcp->pid);
1197 return 0;
H.J. Lu35be5812012-04-16 13:00:01 +02001198 }
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001199 currpers &= ~2; /* map 2,1 to 0,1 */
H.J. Lu35be5812012-04-16 13:00:01 +02001200# endif
H.J. Lu085e4282012-04-17 11:05:04 -07001201 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001202#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001203# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001204 long psr;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001205 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001206 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001207 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001208 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001209 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001210 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001211 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001212 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001213 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001214#elif defined(AARCH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001215 switch (aarch64_io.iov_len) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001216 case sizeof(aarch64_regs):
1217 /* We are in 64-bit mode */
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001218 scno = aarch64_regs.regs[8];
1219 update_personality(tcp, 1);
1220 break;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001221 case sizeof(arm_regs):
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001222 /* We are in 32-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001223 scno = arm_regs.ARM_r7;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001224 update_personality(tcp, 0);
1225 break;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001226 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001227#elif defined(ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001228 /*
1229 * We only need to grab the syscall number on syscall entry.
1230 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001231 if (arm_regs.ARM_ip == 0) {
Roland McGrath0f87c492003-06-03 23:29:04 +00001232 /*
Denys Vlasenko401374e2013-02-06 18:24:39 +01001233 * Note: we only deal with 32-bit CPUs here
Roland McGrath0f87c492003-06-03 23:29:04 +00001234 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001235 if (arm_regs.ARM_cpsr & 0x20) {
Roland McGrath0f87c492003-06-03 23:29:04 +00001236 /*
1237 * Get the Thumb-mode system call number
1238 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001239 scno = arm_regs.ARM_r7;
Roland McGrath0f87c492003-06-03 23:29:04 +00001240 } else {
1241 /*
1242 * Get the ARM-mode system call number
1243 */
1244 errno = 0;
Denys Vlasenko401374e2013-02-06 18:24:39 +01001245 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(arm_regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +00001246 if (errno)
1247 return -1;
1248
Roland McGrathf691bd22006-04-25 07:34:41 +00001249 /* Handle the EABI syscall convention. We do not
1250 bother converting structures between the two
1251 ABIs, but basic functionality should work even
1252 if strace and the traced program have different
1253 ABIs. */
1254 if (scno == 0xef000000) {
Denys Vlasenko401374e2013-02-06 18:24:39 +01001255 scno = arm_regs.ARM_r7;
Roland McGrathf691bd22006-04-25 07:34:41 +00001256 } else {
1257 if ((scno & 0x0ff00000) != 0x0f900000) {
1258 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1259 scno);
1260 return -1;
1261 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001262
Roland McGrathf691bd22006-04-25 07:34:41 +00001263 /*
1264 * Fixup the syscall number
1265 */
1266 scno &= 0x000fffff;
1267 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001268 }
Roland McGrath56703312008-05-20 01:35:55 +00001269 if (scno & 0x0f0000) {
1270 /*
1271 * Handle ARM specific syscall
1272 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001273 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +00001274 scno &= 0x0000ffff;
1275 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001276 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001277
Roland McGrath0f87c492003-06-03 23:29:04 +00001278 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001279 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1280 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001281 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001282#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001283 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001284 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001285#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001286 unsigned long long regs[38];
1287
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001288 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001289 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001290 mips_a3 = regs[REG_A3];
1291 mips_r2 = regs[REG_V0];
Roland McGrath542c2c62008-05-20 01:11:56 +00001292
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001293 scno = mips_r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001294 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001295 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001296 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001297 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001298 return 0;
1299 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001300 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001301#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001302 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001303 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001304 if (upeek(tcp, REG_V0, &scno) < 0)
1305 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001306
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001307 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001308 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001309 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001310 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001311 return 0;
1312 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001313 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001314#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001315 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001316 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001317 if (upeek(tcp, REG_R0, &scno) < 0)
1318 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001319
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001320 /*
1321 * Do some sanity checks to figure out if it's
1322 * really a syscall entry
1323 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001324 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001325 if (alpha_a3 == 0 || alpha_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001326 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001327 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001328 return 0;
1329 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001330 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001331#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001332 /* Disassemble the syscall trap. */
1333 /* Retrieve the syscall trap instruction. */
Denys Vlasenko46455822013-02-05 17:02:59 +01001334 unsigned long trap;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001335 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001336# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001337 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1338 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001339# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001340 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001341# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001342 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001343 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001344
1345 /* Disassemble the trap to see what personality to use. */
1346 switch (trap) {
1347 case 0x91d02010:
1348 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001349 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001350 break;
1351 case 0x91d0206d:
1352 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001353 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001354 break;
1355 case 0x91d02000:
1356 /* SunOS syscall trap. (pers 1) */
1357 fprintf(stderr, "syscall: SunOS no support\n");
1358 return -1;
1359 case 0x91d02008:
1360 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001361 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001362 break;
1363 case 0x91d02009:
1364 /* NetBSD/FreeBSD syscall trap. */
1365 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1366 return -1;
1367 case 0x91d02027:
1368 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001369 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001370 break;
1371 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001372# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001373 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001374# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001375 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001376# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001377 return -1;
1378 }
1379
1380 /* Extract the system call number from the registers. */
1381 if (trap == 0x91d02027)
1382 scno = 156;
1383 else
1384 scno = regs.u_regs[U_REG_G1];
1385 if (scno == 0) {
1386 scno = regs.u_regs[U_REG_O0];
1387 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1388 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001389#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001390 if (upeek(tcp, PT_GR20, &scno) < 0)
1391 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001392#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001393 /*
1394 * In the new syscall ABI, the system call number is in R3.
1395 */
1396 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1397 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001398
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001399 if (scno < 0) {
1400 /* Odd as it may seem, a glibc bug has been known to cause
1401 glibc to issue bogus negative syscall numbers. So for
1402 our purposes, make strace print what it *should* have been */
1403 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001404 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001405 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001406 "Detected glibc bug: bogus system call"
1407 " number = %ld, correcting to %ld\n",
1408 scno,
1409 correct_scno);
1410 scno = correct_scno;
1411 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001412#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001413 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001414 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001415 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001416#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001417 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1418 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001419#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001420 int currpers;
1421 scno = tile_regs.regs[10];
1422# ifdef __tilepro__
1423 currpers = 1;
1424# else
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001425# ifndef PT_FLAGS_COMPAT
1426# define PT_FLAGS_COMPAT 0x10000 /* from Linux 3.8 on */
1427# endif
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001428 if (tile_regs.flags & PT_FLAGS_COMPAT)
1429 currpers = 1;
1430 else
1431 currpers = 0;
1432# endif
1433 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001434#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001435 if (upeek(tcp, 0, &scno) < 0)
1436 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01001437#elif defined(OR1K)
1438 scno = or1k_regs.gpr[11];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001439#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001440
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001441 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001442 return 1;
1443}
1444
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001445/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001446 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001447 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1448 * 1: ok, continue in trace_syscall_entering().
1449 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001450 * ("????" etc) and bail out.
1451 */
Roland McGratha4d48532005-06-08 20:45:28 +00001452static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001453syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001454{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001455 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001456#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001457 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001458 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001459 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1460 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001461 }
H.J. Lu35be5812012-04-16 13:00:01 +02001462#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001463 {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001464 long rax;
1465 if (x86_io.iov_len == sizeof(i386_regs)) {
1466 /* Sign extend from 32 bits */
1467 rax = (int32_t)i386_regs.eax;
1468 } else {
1469 /* Note: in X32 build, this truncates 64 to 32 bits */
1470 rax = x86_64_regs.rax;
1471 }
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001472 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001473 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001474 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1475 return 0;
1476 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001477 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001478#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001479 /* TODO: we already fetched PT_GPR2 in get_scno
1480 * and stored it in syscall_mode, reuse it here
1481 * instead of re-fetching?
1482 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001483 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001484 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001485 if (syscall_mode != -ENOSYS)
1486 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001487 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001488 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001489 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001490 return 0;
1491 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001492#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001493 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001494 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001495 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001496 if (m68k_d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001497 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001498 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", m68k_d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001499 return 0;
1500 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001501#elif defined(IA64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001502 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001503 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001504 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001505 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001506 if (ia32 && ia64_r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001507 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001508 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", ia64_r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001509 return 0;
1510 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001511#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001512 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001513 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001514 if (cris_r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001515 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001516 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", cris_r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001517 return 0;
1518 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001519#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001520 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001521 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001522 if (microblaze_r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001523 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001524 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", microblaze_r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001525 return 0;
1526 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001527#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001528 return 1;
1529}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001530
Denys Vlasenko146b9442012-03-18 22:10:48 +01001531static void
1532internal_fork(struct tcb *tcp)
1533{
1534#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1535# define ARG_FLAGS 1
1536#else
1537# define ARG_FLAGS 0
1538#endif
1539#ifndef CLONE_UNTRACED
1540# define CLONE_UNTRACED 0x00800000
1541#endif
1542 if ((ptrace_setoptions
1543 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1544 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1545 return;
1546
1547 if (!followfork)
1548 return;
1549
1550 if (entering(tcp)) {
1551 /*
1552 * We won't see the new child if clone is called with
1553 * CLONE_UNTRACED, so we keep the same logic with that option
1554 * and don't trace it.
1555 */
1556 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1557 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1558 return;
1559 setbpt(tcp);
1560 } else {
1561 if (tcp->flags & TCB_BPTSET)
1562 clearbpt(tcp);
1563 }
1564}
1565
1566#if defined(TCB_WAITEXECVE)
1567static void
1568internal_exec(struct tcb *tcp)
1569{
1570 /* Maybe we have post-execve SIGTRAP suppressed? */
1571 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1572 return; /* yes, no need to do anything */
1573
1574 if (exiting(tcp) && syserror(tcp))
1575 /* Error in execve, no post-execve SIGTRAP expected */
1576 tcp->flags &= ~TCB_WAITEXECVE;
1577 else
1578 tcp->flags |= TCB_WAITEXECVE;
1579}
1580#endif
1581
1582static void
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001583syscall_fixup_for_fork_exec(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001584{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001585 /*
1586 * We must always trace a few critical system calls in order to
1587 * correctly support following forks in the presence of tracing
1588 * qualifiers.
1589 */
1590 int (*func)();
1591
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001592 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001593 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001594
1595 func = sysent[tcp->scno].sys_func;
1596
1597 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001598 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001599 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001600 ) {
1601 internal_fork(tcp);
1602 return;
1603 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001604
Denys Vlasenko84703742012-02-25 02:38:52 +01001605#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001606 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001607# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001608 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001609# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001610 ) {
1611 internal_exec(tcp);
1612 return;
1613 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001614#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001615}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001616
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001617/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001618static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001619get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001620{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001621 int i, nargs;
1622
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001623 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001624 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001625 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001626 nargs = tcp->u_nargs = MAX_ARGS;
1627
Denys Vlasenko523635f2012-02-25 02:44:25 +01001628#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001629 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001630 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1631 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001632#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001633 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001634 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1635 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001636#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001637 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001638 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001639 long rbs_end;
1640 /* be backwards compatible with kernel < 2.4.4... */
1641# ifndef PT_RBS_END
1642# define PT_RBS_END PT_AR_BSP
1643# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001644
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001645 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1646 return -1;
1647 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001648 return -1;
1649
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001650 sof = (cfm >> 0) & 0x7f;
1651 sol = (cfm >> 7) & 0x7f;
1652 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1653
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001654 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001655 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1656 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1657 return -1;
1658 }
1659 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001660 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1661 PT_R9 /* ECX = out1 */,
1662 PT_R10 /* EDX = out2 */,
1663 PT_R14 /* ESI = out3 */,
1664 PT_R15 /* EDI = out4 */,
1665 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001666
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001667 for (i = 0; i < nargs; ++i) {
1668 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1669 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001670 /* truncate away IVE sign-extension */
1671 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001672 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001673 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001674#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001675 /* N32 and N64 both use up to six registers. */
1676 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001677
1678 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1679 return -1;
1680
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001681 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001682 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001683# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001684 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001685# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001686 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001687#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001688 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001689 long sp;
1690
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001691 if (upeek(tcp, REG_SP, &sp) < 0)
1692 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001693 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001694 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1695 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001696 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001697 (char *)(tcp->u_arg + 4));
1698 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001699 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001700 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001701 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001702 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001703#elif defined(POWERPC)
1704# ifndef PT_ORIG_R3
1705# define PT_ORIG_R3 34
1706# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001707 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001708 if (upeek(tcp, (i==0) ?
1709 (sizeof(unsigned long) * PT_ORIG_R3) :
1710 ((i+PT_R3) * sizeof(unsigned long)),
1711 &tcp->u_arg[i]) < 0)
1712 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001713 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001714#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001715 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001716 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001717#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001718 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001719 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1720 return -1;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001721#elif defined(ARM) || defined(AARCH64)
1722# if defined(AARCH64)
1723 if (tcp->currpers == 1)
1724 for (i = 0; i < nargs; ++i)
1725 tcp->u_arg[i] = aarch64_regs.regs[i];
1726 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001727# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001728 for (i = 0; i < nargs; ++i)
Denys Vlasenko401374e2013-02-06 18:24:39 +01001729 tcp->u_arg[i] = arm_regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001730#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001731 (void)i;
1732 (void)nargs;
1733 tcp->u_arg[0] = regs.r12;
1734 tcp->u_arg[1] = regs.r11;
1735 tcp->u_arg[2] = regs.r10;
1736 tcp->u_arg[3] = regs.r9;
1737 tcp->u_arg[4] = regs.r5;
1738 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001739#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001740 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 +02001741
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001742 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001743 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1744 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001745#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001746 static const int syscall_regs[MAX_ARGS] = {
1747 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1748 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001749 };
1750
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001751 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001752 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001753 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001754#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001755 int i;
1756 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001757 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001758
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001759 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001760 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1761 return -1;
Denys Vlasenko6cf36052013-02-15 15:01:38 +01001762#elif defined(I386)
1763 (void)i;
1764 (void)nargs;
1765 tcp->u_arg[0] = i386_regs.ebx;
1766 tcp->u_arg[1] = i386_regs.ecx;
1767 tcp->u_arg[2] = i386_regs.edx;
1768 tcp->u_arg[3] = i386_regs.esi;
1769 tcp->u_arg[4] = i386_regs.edi;
1770 tcp->u_arg[5] = i386_regs.ebp;
H.J. Lu35be5812012-04-16 13:00:01 +02001771#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001772 (void)i;
1773 (void)nargs;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001774 if (x86_io.iov_len != sizeof(i386_regs)) {
1775 /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001776 tcp->u_arg[0] = x86_64_regs.rdi;
1777 tcp->u_arg[1] = x86_64_regs.rsi;
1778 tcp->u_arg[2] = x86_64_regs.rdx;
1779 tcp->u_arg[3] = x86_64_regs.r10;
1780 tcp->u_arg[4] = x86_64_regs.r8;
1781 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001782# ifdef X32
1783 tcp->ext_arg[0] = x86_64_regs.rdi;
1784 tcp->ext_arg[1] = x86_64_regs.rsi;
1785 tcp->ext_arg[2] = x86_64_regs.rdx;
1786 tcp->ext_arg[3] = x86_64_regs.r10;
1787 tcp->ext_arg[4] = x86_64_regs.r8;
1788 tcp->ext_arg[5] = x86_64_regs.r9;
1789# endif
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001790 } else {
1791 /* i386 ABI */
Denys Vlasenko6cf36052013-02-15 15:01:38 +01001792 /* Zero-extend from 32 bits */
1793 /* Use widen_to_long(tcp->u_arg[N]) in syscall handlers
1794 * if you need to use *sign-extended* parameter.
1795 */
1796 tcp->u_arg[0] = (long)(uint32_t)i386_regs.ebx;
1797 tcp->u_arg[1] = (long)(uint32_t)i386_regs.ecx;
1798 tcp->u_arg[2] = (long)(uint32_t)i386_regs.edx;
1799 tcp->u_arg[3] = (long)(uint32_t)i386_regs.esi;
1800 tcp->u_arg[4] = (long)(uint32_t)i386_regs.edi;
1801 tcp->u_arg[5] = (long)(uint32_t)i386_regs.ebp;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001802 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001803#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001804 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001805 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1806 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001807#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001808 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001809 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001810 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001811 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001812
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001813 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001814 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1815 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001816#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001817 for (i = 0; i < nargs; ++i)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001818 tcp->u_arg[i] = tile_regs.regs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001819#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001820 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001821 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1822 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01001823#elif defined(OR1K)
1824 (void)nargs;
1825 for (i = 0; i < 6; ++i)
1826 tcp->u_arg[i] = or1k_regs.gpr[3 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001827#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001828 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001829 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1830 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001831#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001832 return 1;
1833}
1834
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001835static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001836trace_syscall_entering(struct tcb *tcp)
1837{
1838 int res, scno_good;
1839
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001840#if defined TCB_WAITEXECVE
1841 if (tcp->flags & TCB_WAITEXECVE) {
1842 /* This is the post-execve SIGTRAP. */
1843 tcp->flags &= ~TCB_WAITEXECVE;
1844 return 0;
1845 }
1846#endif
1847
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001848 scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001849 if (res == 0)
1850 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001851 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001852 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001853 if (res == 0)
1854 return res;
1855 if (res == 1)
1856 res = get_syscall_args(tcp);
1857 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001858
1859 if (res != 1) {
1860 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001861 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001862 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001863 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001864 tprintf("syscall_%lu(", tcp->scno);
1865 else
1866 tprintf("%s(", sysent[tcp->scno].sys_name);
1867 /*
1868 * " <unavailable>" will be added later by the code which
1869 * detects ptrace errors.
1870 */
1871 goto ret;
1872 }
1873
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001874#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1875 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001876# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001877 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001878 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001879 break;
1880 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001881# endif
1882# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001883 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001884 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001885 break;
1886 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001887# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001888 break;
1889 }
1890#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1891
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001892 if (need_fork_exec_workarounds)
1893 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001894
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001895 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001896 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1897 (tracing_paths && !pathtrace_match(tcp))) {
1898 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1899 return 0;
1900 }
1901
1902 tcp->flags &= ~TCB_FILTERED;
1903
1904 if (cflag == CFLAG_ONLY_STATS) {
1905 res = 0;
1906 goto ret;
1907 }
1908
1909 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001910 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001911 tprintf("syscall_%lu(", tcp->scno);
1912 else
1913 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001914 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001915 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1916 sysent[tcp->scno].sys_func != sys_exit))
1917 res = printargs(tcp);
1918 else
1919 res = (*sysent[tcp->scno].sys_func)(tcp);
1920
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001921 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001922 ret:
1923 tcp->flags |= TCB_INSYSCALL;
1924 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001925 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001926 gettimeofday(&tcp->etime, NULL);
1927 return res;
1928}
1929
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001930/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001931 * 1: ok, continue in trace_syscall_exiting().
1932 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001933 * ("????" etc) and bail out.
1934 */
1935static int
1936get_syscall_result(struct tcb *tcp)
1937{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001938#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001939 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1940 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001941#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001942# define SO_MASK 0x10000000
1943 {
1944 long flags;
1945 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1946 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001947 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001948 return -1;
1949 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001950 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001951 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001952#elif defined(AVR32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001953 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001954#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001955 if (upeek(tcp, PT_R0, &bfin_r0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001956 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001957#elif defined(I386)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001958 /* already done by get_regs */
H.J. Lu35be5812012-04-16 13:00:01 +02001959#elif defined(X86_64) || defined(X32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001960 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001961#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001962# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001963 long psr;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001964 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1965 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001966 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001967 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001968 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001969 return -1;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001970#elif defined(ARM)
1971 /* already done by get_regs */
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001972#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001973 /* register reading already done by get_regs */
1974
1975 /* Used to do this, but we did it on syscall entry already: */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001976 /* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
1977 * else it's personality 0.
1978 */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001979 /*update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));*/
Denys Vlasenko523635f2012-02-25 02:44:25 +01001980#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001981 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001982 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001983#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001984 unsigned long long regs[38];
1985
1986 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1987 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001988 mips_a3 = regs[REG_A3];
1989 mips_r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001990#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001991 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001992 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001993 if (upeek(tcp, REG_V0, &mips_r2) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001994 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001995#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001996 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001997 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001998 if (upeek(tcp, REG_R0, &alpha_r0) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001999 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002000#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002001 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002002#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002003 if (upeek(tcp, PT_GR28, &hppa_r28) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002004 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002005#elif defined(SH)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002006 /* new syscall ABI returns result in R0 */
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002007 if (upeek(tcp, 4*REG_REG0, (long *)&sh_r0) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002008 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002009#elif defined(SH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002010 /* ABI defines result returned in r9 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002011 if (upeek(tcp, REG_GENERAL(9), (long *)&sh64_r9) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002012 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002013#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002014 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002015 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002016#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002017 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002018#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002019 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002020 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01002021#elif defined(OR1K)
2022 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002023#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002024 return 1;
2025}
2026
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002027/* Called at each syscall exit */
2028static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002029syscall_fixup_on_sysexit(struct tcb *tcp)
2030{
Denys Vlasenko523635f2012-02-25 02:44:25 +01002031#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002032 if (syscall_mode != -ENOSYS)
2033 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02002034 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002035 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
2036 /*
2037 * Return from execve.
2038 * Fake a return value of zero. We leave the TCB_WAITEXECVE
2039 * flag set for the post-execve SIGTRAP to see and reset.
2040 */
2041 gpr2 = 0;
2042 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002043#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002044}
2045
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002046/*
2047 * Check the syscall return value register value for whether it is
2048 * a negated errno code indicating an error, or a success return value.
2049 */
2050static inline int
2051is_negated_errno(unsigned long int val)
2052{
2053 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002054#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01002055 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002056 val = (unsigned int) val;
2057 max = (unsigned int) max;
2058 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002059#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002060 return val > max;
2061}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002062
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002063#if defined(X32)
2064static inline int
2065is_negated_errno_x32(unsigned long long val)
2066{
2067 unsigned long long max = -(long long) nerrnos;
2068 /*
2069 * current_wordsize is 4 even in personality 0 (native X32)
2070 * but truncation _must not_ be done in it.
2071 * can't check current_wordsize here!
2072 */
2073 if (current_personality != 0) {
2074 val = (uint32_t) val;
2075 max = (uint32_t) max;
2076 }
2077 return val > max;
2078}
2079#endif
2080
Denys Vlasenko907735a2012-03-21 00:23:16 +01002081/* Returns:
2082 * 1: ok, continue in trace_syscall_exiting().
2083 * -1: error, trace_syscall_exiting() should print error indicator
2084 * ("????" etc) and bail out.
2085 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002086static int
2087get_error(struct tcb *tcp)
2088{
2089 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002090 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002091 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002092 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
2093 check_errno = 0;
2094 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002095#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002096 if (check_errno && is_negated_errno(gpr2)) {
2097 tcp->u_rval = -1;
2098 u_error = -gpr2;
2099 }
2100 else {
2101 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002102 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002103#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002104 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002105 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002106 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002107 }
2108 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002109 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002110 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002111#elif defined(X86_64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002112 long rax;
2113 if (x86_io.iov_len == sizeof(i386_regs)) {
2114 /* Sign extend from 32 bits */
2115 rax = (int32_t)i386_regs.eax;
2116 } else {
2117 rax = x86_64_regs.rax;
2118 }
2119 if (check_errno && is_negated_errno(rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002120 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002121 u_error = -rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002122 }
2123 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002124 tcp->u_rval = rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002125 }
2126#elif defined(X32)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002127 /* In X32, return value is 64-bit (llseek uses one).
2128 * Using merely "long rax" would not work.
2129 */
2130 long long rax;
2131 if (x86_io.iov_len == sizeof(i386_regs)) {
2132 /* Sign extend from 32 bits */
2133 rax = (int32_t)i386_regs.eax;
2134 } else {
2135 rax = x86_64_regs.rax;
2136 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002137 /* Careful: is_negated_errno() works only on longs */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002138 if (check_errno && is_negated_errno_x32(rax)) {
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002139 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002140 u_error = -rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002141 }
2142 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002143 tcp->u_rval = rax; /* truncating */
2144 tcp->u_lrval = rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002145 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002146#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002147 if (ia32) {
2148 int err;
2149
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002150 err = (int)ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002151 if (check_errno && is_negated_errno(err)) {
2152 tcp->u_rval = -1;
2153 u_error = -err;
2154 }
2155 else {
2156 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002157 }
2158 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002159 if (check_errno && ia64_r10) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002160 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002161 u_error = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002162 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002163 tcp->u_rval = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002164 }
2165 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002166#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002167 if (check_errno && mips_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002168 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002169 u_error = mips_r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002170 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002171 tcp->u_rval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002172# if defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002173 tcp->u_lrval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002174# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002175 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002176#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002177 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002178 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002179 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002180 }
2181 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002182 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002183 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002184#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002185 if (check_errno && is_negated_errno(m68k_d0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002186 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002187 u_error = -m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002188 }
2189 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002190 tcp->u_rval = m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002191 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002192#elif defined(ARM) || defined(AARCH64)
2193# if defined(AARCH64)
2194 if (tcp->currpers == 1) {
2195 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2196 tcp->u_rval = -1;
2197 u_error = -aarch64_regs.regs[0];
2198 }
2199 else {
2200 tcp->u_rval = aarch64_regs.regs[0];
2201 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002202 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002203 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01002204# endif
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002205 {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002206 if (check_errno && is_negated_errno(arm_regs.ARM_r0)) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002207 tcp->u_rval = -1;
Denys Vlasenko401374e2013-02-06 18:24:39 +01002208 u_error = -arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002209 }
2210 else {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002211 tcp->u_rval = arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002212 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002213 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002214#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002215 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
2216 tcp->u_rval = -1;
2217 u_error = -regs.r12;
2218 }
2219 else {
2220 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002221 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002222#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002223 if (check_errno && is_negated_errno(bfin_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002224 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002225 u_error = -bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002226 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002227 tcp->u_rval = bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002228 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002229#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002230 if (check_errno && alpha_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002231 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002232 u_error = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002233 }
2234 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002235 tcp->u_rval = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002236 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002237#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002238 if (check_errno && regs.psr & PSR_C) {
2239 tcp->u_rval = -1;
2240 u_error = regs.u_regs[U_REG_O0];
2241 }
2242 else {
2243 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002244 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002245#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002246 if (check_errno && regs.tstate & 0x1100000000UL) {
2247 tcp->u_rval = -1;
2248 u_error = regs.u_regs[U_REG_O0];
2249 }
2250 else {
2251 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002252 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002253#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002254 if (check_errno && is_negated_errno(hppa_r28)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002255 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002256 u_error = -hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002257 }
2258 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002259 tcp->u_rval = hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002260 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002261#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002262 if (check_errno && is_negated_errno(sh_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002263 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002264 u_error = -sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002265 }
2266 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002267 tcp->u_rval = sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002268 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002269#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002270 if (check_errno && is_negated_errno(sh64_r9)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002271 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002272 u_error = -sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002273 }
2274 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002275 tcp->u_rval = sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002276 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002277#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002278 if (check_errno && cris_r10 && (unsigned) -cris_r10 < nerrnos) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002279 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002280 u_error = -cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002281 }
2282 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002283 tcp->u_rval = cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002284 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002285#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002286 /*
2287 * The standard tile calling convention returns the value (or negative
2288 * errno) in r0, and zero (or positive errno) in r1.
2289 * Until at least kernel 3.8, however, the r1 value is not reflected
2290 * in ptregs at this point, so we use r0 here.
2291 */
2292 if (check_errno && is_negated_errno(tile_regs.regs[0])) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002293 tcp->u_rval = -1;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002294 u_error = -tile_regs.regs[0];
2295 } else {
2296 tcp->u_rval = tile_regs.regs[0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002297 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002298#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002299 if (check_errno && is_negated_errno(microblaze_r3)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002300 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002301 u_error = -microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002302 }
2303 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002304 tcp->u_rval = microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002305 }
Christian Svensson492f81f2013-02-14 13:26:27 +01002306#elif defined(OR1K)
2307 if (check_errno && is_negated_errno(or1k_regs.gpr[11])) {
2308 tcp->u_rval = -1;
2309 u_error = -or1k_regs.gpr[11];
2310 }
2311 else {
2312 tcp->u_rval = or1k_regs.gpr[11];
2313 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002314#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002315 tcp->u_error = u_error;
2316 return 1;
2317}
2318
2319static void
2320dumpio(struct tcb *tcp)
2321{
2322 if (syserror(tcp))
2323 return;
2324 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
2325 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002326 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002327 return;
2328 if (sysent[tcp->scno].sys_func == printargs)
2329 return;
2330 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
2331 if (sysent[tcp->scno].sys_func == sys_read ||
2332 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002333 sysent[tcp->scno].sys_func == sys_recv ||
2334 sysent[tcp->scno].sys_func == sys_recvfrom)
2335 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
2336 else if (sysent[tcp->scno].sys_func == sys_readv)
2337 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2338 return;
2339 }
2340 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
2341 if (sysent[tcp->scno].sys_func == sys_write ||
2342 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002343 sysent[tcp->scno].sys_func == sys_send ||
2344 sysent[tcp->scno].sys_func == sys_sendto)
2345 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
2346 else if (sysent[tcp->scno].sys_func == sys_writev)
2347 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2348 return;
2349 }
2350}
2351
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002352static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002353trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002354{
2355 int sys_res;
2356 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002357 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002358 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002359
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002360 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002361 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002362 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002363
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002364#if SUPPORTED_PERSONALITIES > 1
2365 update_personality(tcp, tcp->currpers);
2366#endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002367 res = (get_regs_error ? -1 : get_syscall_result(tcp));
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002368 if (res == 1) {
2369 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01002370 res = get_error(tcp); /* returns 1 or -1 */
2371 if (res == 1) {
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01002372 if (need_fork_exec_workarounds)
2373 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01002374 if (filtered(tcp)) {
2375 goto ret;
2376 }
2377 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002378 }
2379
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002380 if (cflag) {
2381 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002382 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002383 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002384 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002385 }
2386 }
2387
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002388 /* If not in -ff mode, and printing_tcp != tcp,
2389 * then the log currently does not end with output
2390 * of _our syscall entry_, but with something else.
2391 * We need to say which syscall's return is this.
2392 *
2393 * Forced reprinting via TCB_REPRINT is used only by
2394 * "strace -ff -oLOG test/threaded_execve" corner case.
2395 * It's the only case when -ff mode needs reprinting.
2396 */
2397 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2398 tcp->flags &= ~TCB_REPRINT;
2399 printleader(tcp);
2400 if (!SCNO_IN_RANGE(tcp->scno))
2401 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2402 else
2403 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2404 }
2405 printing_tcp = tcp;
2406
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002407 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002408 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002409 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002410 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002411 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002412 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002413 tcp->flags &= ~TCB_INSYSCALL;
2414 return res;
2415 }
2416
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002417 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002418 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002419 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002420 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002421 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002422 /* FIXME: not_failing_only (IOW, option -z) is broken:
2423 * failure of syscall is known only after syscall return.
2424 * Thus we end up with something like this on, say, ENOENT:
2425 * open("doesnt_exist", O_RDONLY <unfinished ...>
2426 * {next syscall decode}
2427 * whereas the intended result is that open(...) line
2428 * is not shown at all.
2429 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002430 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002431 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002432 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2433 }
2434
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002435 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002436 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002437 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002438 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002439 qual_flags[tcp->scno] & QUAL_RAW) {
2440 if (u_error)
2441 tprintf("= -1 (errno %ld)", u_error);
2442 else
2443 tprintf("= %#lx", tcp->u_rval);
2444 }
2445 else if (!(sys_res & RVAL_NONE) && u_error) {
2446 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002447 /* Blocked signals do not interrupt any syscalls.
2448 * In this case syscalls don't return ERESTARTfoo codes.
2449 *
2450 * Deadly signals set to SIG_DFL interrupt syscalls
2451 * and kill the process regardless of which of the codes below
2452 * is returned by the interrupted syscall.
2453 * In some cases, kernel forces a kernel-generated deadly
2454 * signal to be unblocked and set to SIG_DFL (and thus cause
2455 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2456 * or SIGILL. (The alternative is to leave process spinning
2457 * forever on the faulty instruction - not useful).
2458 *
2459 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2460 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2461 * but kernel will always restart them.
2462 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002463 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002464 /* Most common type of signal-interrupted syscall exit code.
2465 * The system call will be restarted with the same arguments
2466 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2467 */
2468 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002469 break;
2470 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002471 /* Rare. For example, fork() returns this if interrupted.
2472 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2473 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002474 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002475 break;
2476 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002477 /* pause(), rt_sigsuspend() etc use this code.
2478 * SA_RESTART is ignored (assumed not set):
2479 * syscall won't restart (will return EINTR instead)
2480 * even after signal with SA_RESTART set.
2481 * However, after SIG_IGN or SIG_DFL signal it will.
2482 */
2483 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002484 break;
2485 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002486 /* Syscalls like nanosleep(), poll() which can't be
2487 * restarted with their original arguments use this
2488 * code. Kernel will execute restart_syscall() instead,
2489 * which changes arguments before restarting syscall.
2490 * SA_RESTART is ignored (assumed not set) similarly
2491 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2492 * since restart data is saved in "restart block"
2493 * in task struct, and if signal handler uses a syscall
2494 * which in turn saves another such restart block,
2495 * old data is lost and restart becomes impossible)
2496 */
2497 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002498 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002499 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002500 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002501 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002502 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002503 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002504 strerror(u_error));
2505 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002506 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002507 strerror(u_error));
2508 break;
2509 }
2510 if ((sys_res & RVAL_STR) && tcp->auxstr)
2511 tprintf(" (%s)", tcp->auxstr);
2512 }
2513 else {
2514 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002515 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002516 else {
2517 switch (sys_res & RVAL_MASK) {
2518 case RVAL_HEX:
2519 tprintf("= %#lx", tcp->u_rval);
2520 break;
2521 case RVAL_OCTAL:
2522 tprintf("= %#lo", tcp->u_rval);
2523 break;
2524 case RVAL_UDECIMAL:
2525 tprintf("= %lu", tcp->u_rval);
2526 break;
2527 case RVAL_DECIMAL:
2528 tprintf("= %ld", tcp->u_rval);
2529 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002530#if defined(LINUX_MIPSN32) || defined(X32)
2531 /*
2532 case RVAL_LHEX:
2533 tprintf("= %#llx", tcp->u_lrval);
2534 break;
2535 case RVAL_LOCTAL:
2536 tprintf("= %#llo", tcp->u_lrval);
2537 break;
2538 */
2539 case RVAL_LUDECIMAL:
2540 tprintf("= %llu", tcp->u_lrval);
2541 break;
2542 /*
2543 case RVAL_LDECIMAL:
2544 tprintf("= %lld", tcp->u_lrval);
2545 break;
2546 */
2547#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002548 default:
2549 fprintf(stderr,
2550 "invalid rval format\n");
2551 break;
2552 }
2553 }
2554 if ((sys_res & RVAL_STR) && tcp->auxstr)
2555 tprintf(" (%s)", tcp->auxstr);
2556 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002557 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002558 tv_sub(&tv, &tv, &tcp->etime);
2559 tprintf(" <%ld.%06ld>",
2560 (long) tv.tv_sec, (long) tv.tv_usec);
2561 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002562 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002563 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002564 line_ended();
2565
Denys Vlasenko3b738812011-08-22 02:06:35 +02002566 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002567 tcp->flags &= ~TCB_INSYSCALL;
2568 return 0;
2569}
2570
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002571int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002572trace_syscall(struct tcb *tcp)
2573{
2574 return exiting(tcp) ?
2575 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2576}