blob: b1a407b0eff4807fcacf1144d51134fb51486f9c [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 Vlasenko48e4c1b2013-02-16 08:23:40 +0100645 val = sparc_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 Vlasenko48e4c1b2013-02-16 08:23:40 +0100735static struct pt_regs avr32_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100736#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100737struct pt_regs sparc_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;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100802 if (upeek(tcp, PT_B0, &ip) < 0) {
803 PRINTBADPC;
804 return;
805 }
806 tprintf("[%08lx] ", ip);
807#elif defined(POWERPC)
808 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100809 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
810 PRINTBADPC;
811 return;
812 }
813# ifdef POWERPC64
814 tprintf("[%016lx] ", pc);
815# else
816 tprintf("[%08lx] ", pc);
817# endif
818#elif defined(M68K)
819 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100820 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
821 tprints("[????????] ");
822 return;
823 }
824 tprintf("[%08lx] ", pc);
825#elif defined(ALPHA)
826 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100827 if (upeek(tcp, REG_PC, &pc) < 0) {
828 tprints("[????????????????] ");
829 return;
830 }
831 tprintf("[%08lx] ", pc);
832#elif defined(SPARC)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100833 tprintf("[%08lx] ", sparc_regs.pc);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100834#elif defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100835 tprintf("[%08lx] ", sparc_regs.tpc);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100836#elif defined(HPPA)
837 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100838 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
839 tprints("[????????] ");
840 return;
841 }
842 tprintf("[%08lx] ", pc);
843#elif defined(MIPS)
844 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100845 if (upeek(tcp, REG_EPC, &pc) < 0) {
846 tprints("[????????] ");
847 return;
848 }
849 tprintf("[%08lx] ", pc);
850#elif defined(SH)
851 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100852 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
853 tprints("[????????] ");
854 return;
855 }
856 tprintf("[%08lx] ", pc);
857#elif defined(SH64)
858 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100859 if (upeek(tcp, REG_PC, &pc) < 0) {
860 tprints("[????????????????] ");
861 return;
862 }
863 tprintf("[%08lx] ", pc);
864#elif defined(ARM)
Denys Vlasenko401374e2013-02-06 18:24:39 +0100865 tprintf("[%08lx] ", arm_regs.ARM_pc);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100866#elif defined(AARCH64)
867 /* tprintf("[%016lx] ", aarch64_regs.regs[???]); */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100868#elif defined(AVR32)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100869 tprintf("[%08lx] ", avr32_regs.pc);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100870#elif defined(BFIN)
871 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100872 if (upeek(tcp, PT_PC, &pc) < 0) {
873 PRINTBADPC;
874 return;
875 }
876 tprintf("[%08lx] ", pc);
877#elif defined(CRISV10)
878 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100879 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
880 PRINTBADPC;
881 return;
882 }
883 tprintf("[%08lx] ", pc);
884#elif defined(CRISV32)
885 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100886 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
887 PRINTBADPC;
888 return;
889 }
890 tprintf("[%08lx] ", pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100891#elif defined(TILE)
892# ifdef _LP64
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500893 tprintf("[%016lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100894# else
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500895 tprintf("[%08lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100896# endif
Christian Svensson492f81f2013-02-14 13:26:27 +0100897#elif defined(OR1K)
898 tprintf("[%08lx] ", or1k_regs.pc);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100899#endif /* architecture */
900}
901
Denys Vlasenko7270de52013-02-21 15:46:34 +0100902/* Shuffle syscall numbers so that we don't have huge gaps in syscall table.
903 * The shuffling should be reversible: shuffle_scno(shuffle_scno(n)) == n.
904 */
905#if defined(ARM) /* So far only ARM needs this */
906static long
907shuffle_scno(unsigned long scno)
908{
909 if (scno <= ARM_LAST_ORDINARY_SYSCALL)
910 return scno;
911
912 /* __ARM_NR_cmpxchg? Swap with LAST_ORDINARY+1 */
913 if (scno == 0x000ffff0)
914 return ARM_LAST_ORDINARY_SYSCALL+1;
915 if (scno == ARM_LAST_ORDINARY_SYSCALL+1)
916 return 0x000ffff0;
917
918 /* Is it ARM specific syscall?
919 * Swap with [LAST_ORDINARY+2, LAST_ORDINARY+2 + LAST_SPECIAL] range.
920 */
921 if (scno >= 0x000f0000
922 && scno <= 0x000f0000 + ARM_LAST_SPECIAL_SYSCALL
923 ) {
924 return scno - 0x000f0000 + (ARM_LAST_ORDINARY_SYSCALL+2);
925 }
926 if (/* scno >= ARM_LAST_ORDINARY_SYSCALL+2 - always true */ 1
927 && scno <= (ARM_LAST_ORDINARY_SYSCALL+2) + ARM_LAST_SPECIAL_SYSCALL
928 ) {
929 return scno + 0x000f0000 - (ARM_LAST_ORDINARY_SYSCALL+2);
930 }
931
932 return scno;
933}
934#else
935# define shuffle_scno(scno) ((long)(scno))
936#endif
937
938static char*
939undefined_scno_name(struct tcb *tcp)
940{
941 static char buf[sizeof("syscall_%lu") + sizeof(long)*3];
942
943 sprintf(buf, "syscall_%lu", shuffle_scno(tcp->scno));
944 return buf;
945}
946
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100947#ifndef get_regs
948long get_regs_error;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100949void
950get_regs(pid_t pid)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100951{
952# if defined(AVR32)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100953 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &avr32_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100954# elif defined(I386)
955 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &i386_regs);
956# elif defined(X86_64) || defined(X32)
Denys Vlasenkoe3b248d2013-02-15 00:24:19 +0100957 /*
958 * PTRACE_GETREGSET was introduced in 2.6.33.
959 * Let's be paranoid and require a bit later kernel.
960 */
961 if (os_release >= KERNEL_VERSION(2,6,35)) {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100962 /*x86_io.iov_base = &x86_regs_union; - already is */
963 x86_io.iov_len = sizeof(x86_regs_union);
964 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (long) &x86_io);
965 } else {
966 /* Use old method, with heuristical detection of 32-bitness */
967 x86_io.iov_len = sizeof(x86_64_regs);
968 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &x86_64_regs);
969 if (!get_regs_error && x86_64_regs.cs == 0x23) {
970 x86_io.iov_len = sizeof(i386_regs);
971 /*
972 * The order is important: i386_regs and x86_64_regs
973 * are overlaid in memory!
974 */
975 i386_regs.ebx = x86_64_regs.rbx;
976 i386_regs.ecx = x86_64_regs.rcx;
977 i386_regs.edx = x86_64_regs.rdx;
978 i386_regs.esi = x86_64_regs.rsi;
979 i386_regs.edi = x86_64_regs.rdi;
980 i386_regs.ebp = x86_64_regs.rbp;
981 i386_regs.eax = x86_64_regs.rax;
982 /*i386_regs.xds = x86_64_regs.ds; unused by strace */
983 /*i386_regs.xes = x86_64_regs.es; ditto... */
984 /*i386_regs.xfs = x86_64_regs.fs;*/
985 /*i386_regs.xgs = x86_64_regs.gs;*/
986 i386_regs.orig_eax = x86_64_regs.orig_rax;
987 i386_regs.eip = x86_64_regs.rip;
988 /*i386_regs.xcs = x86_64_regs.cs;*/
989 /*i386_regs.eflags = x86_64_regs.eflags;*/
990 i386_regs.esp = x86_64_regs.rsp;
991 /*i386_regs.xss = x86_64_regs.ss;*/
992 }
993 }
Denys Vlasenko401374e2013-02-06 18:24:39 +0100994# elif defined(ARM)
995 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (void *)&arm_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100996# elif defined(AARCH64)
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100997 /*aarch64_io.iov_base = &arm_regs_union; - already is */
998 aarch64_io.iov_len = sizeof(arm_regs_union);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100999 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void *)&aarch64_io);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001000# if 0
1001 /* Paranoia checks */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001002 if (get_regs_error)
1003 return;
1004 switch (aarch64_io.iov_len) {
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001005 case sizeof(aarch64_regs):
1006 /* We are in 64-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001007 break;
1008 case sizeof(arm_regs):
1009 /* We are in 32-bit mode */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001010 break;
1011 default:
1012 get_regs_error = -1;
1013 break;
1014 }
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001015# endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001016# elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001017 get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&sparc_regs, 0);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001018# elif defined(TILE)
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -05001019 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &tile_regs);
Christian Svensson492f81f2013-02-14 13:26:27 +01001020# elif defined(OR1K)
1021 or1k_io.iov_len = sizeof(or1k_regs);
1022 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &or1k_io);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001023# endif
1024}
1025#endif
1026
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001027/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001028 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1029 * 1: ok, continue in trace_syscall_entering().
1030 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001031 * ("????" etc) and bail out.
1032 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001033static int
Denys Vlasenko06602d92011-08-24 17:53:52 +02001034get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001035{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001036 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001037
Denys Vlasenko523635f2012-02-25 02:44:25 +01001038#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001039 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001040 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +00001041
1042 if (syscall_mode != -ENOSYS) {
1043 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001044 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +00001045 */
1046 scno = syscall_mode;
1047 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001048 /*
Michal Ludvig882eda82002-11-11 12:50:47 +00001049 * Old style of "passing" the scno via the SVC instruction.
1050 */
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001051 long psw;
Michal Ludvig882eda82002-11-11 12:50:47 +00001052 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001053 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +02001054 static const int gpr_offset[16] = {
1055 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
1056 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
1057 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
1058 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
1059 };
Roland McGrath761b5d72002-12-15 23:58:31 +00001060
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001061 if (upeek(tcp, PT_PSWADDR, &psw) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +00001062 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +00001063 errno = 0;
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001064 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(psw - sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +00001065 if (errno) {
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001066 perror_msg("%s", "peektext(psw-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +00001067 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +00001068 }
Michal Ludvig882eda82002-11-11 12:50:47 +00001069
1070 /*
1071 * We have to check if the SVC got executed directly or via an
1072 * EXECUTE instruction. In case of EXECUTE it is necessary to do
1073 * instruction decoding to derive the system call number.
1074 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
1075 * so that this doesn't work if a SVC opcode is part of an EXECUTE
1076 * opcode. Since there is no way to find out the opcode size this
1077 * is the best we can do...
1078 */
Michal Ludvig882eda82002-11-11 12:50:47 +00001079 if ((opcode & 0xff00) == 0x0a00) {
1080 /* SVC opcode */
1081 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +00001082 }
Michal Ludvig882eda82002-11-11 12:50:47 +00001083 else {
1084 /* SVC got executed by EXECUTE instruction */
1085
1086 /*
1087 * Do instruction decoding of EXECUTE. If you really want to
1088 * understand this, read the Principles of Operations.
1089 */
1090 svc_addr = (void *) (opcode & 0xfff);
1091
1092 tmp = 0;
1093 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001094 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001095 return -1;
1096 svc_addr += tmp;
1097
1098 tmp = 0;
1099 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001100 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001101 return -1;
1102 svc_addr += tmp;
1103
Denys Vlasenkofb036672009-01-23 16:30:26 +00001104 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +00001105 if (errno)
1106 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001107# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +00001108 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001109# else
Michal Ludvig882eda82002-11-11 12:50:47 +00001110 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001111# endif
Michal Ludvig882eda82002-11-11 12:50:47 +00001112 tmp = 0;
1113 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001114 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001115 return -1;
1116
1117 scno = (scno | tmp) & 0xff;
1118 }
1119 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001120#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001121 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001122 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001123# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001124 /* TODO: speed up strace by not doing this at every syscall.
1125 * We only need to do it after execve.
1126 */
1127 int currpers;
1128 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +02001129
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001130 /* Check for 64/32 bit mode. */
1131 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
1132 return -1;
1133 /* SF is bit 0 of MSR */
1134 if (val < 0)
1135 currpers = 0;
1136 else
1137 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001138 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001139# endif
1140#elif defined(AVR32)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001141 scno = avr32_regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001142#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001143 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001144 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001145#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001146 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +02001147#elif defined(X86_64) || defined(X32)
1148# ifndef __X32_SYSCALL_BIT
1149# define __X32_SYSCALL_BIT 0x40000000
1150# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001151 int currpers;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001152# if 1
1153 /* GETREGSET of NT_PRSTATUS tells us regset size,
1154 * which unambiguously detects i386.
1155 *
1156 * Linux kernel distinguishes x86-64 and x32 processes
1157 * solely by looking at __X32_SYSCALL_BIT:
1158 * arch/x86/include/asm/compat.h::is_x32_task():
1159 * if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)
1160 * return true;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001161 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001162 if (x86_io.iov_len == sizeof(i386_regs)) {
1163 scno = i386_regs.orig_eax;
1164 currpers = 1;
1165 } else {
1166 scno = x86_64_regs.orig_rax;
1167 currpers = 0;
1168 if (scno & __X32_SYSCALL_BIT) {
1169 scno -= __X32_SYSCALL_BIT;
1170 currpers = 2;
1171 }
1172 }
1173# elif 0
1174 /* cs = 0x33 for long mode (native 64 bit and x32)
1175 * cs = 0x23 for compatibility mode (32 bit)
1176 * ds = 0x2b for x32 mode (x86-64 in 32 bit)
1177 */
1178 scno = x86_64_regs.orig_rax;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001179 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001180 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +02001181 case 0x33:
1182 if (x86_64_regs.ds == 0x2b) {
1183 currpers = 2;
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001184 scno &= ~__X32_SYSCALL_BIT;
H.J. Lu35be5812012-04-16 13:00:01 +02001185 } else
1186 currpers = 0;
1187 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001188 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001189 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001190 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001191 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001192 currpers = current_personality;
1193 break;
1194 }
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001195# elif 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001196 /* This version analyzes the opcode of a syscall instruction.
1197 * (int 0x80 on i386 vs. syscall on x86-64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001198 * It works, but is too complicated, and strictly speaking, unreliable.
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001199 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001200 unsigned long call, rip = x86_64_regs.rip;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001201 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
1202 rip -= 2;
1203 errno = 0;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001204 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001205 if (errno)
1206 fprintf(stderr, "ptrace_peektext failed: %s\n",
1207 strerror(errno));
1208 switch (call & 0xffff) {
1209 /* x86-64: syscall = 0x0f 0x05 */
1210 case 0x050f: currpers = 0; break;
1211 /* i386: int 0x80 = 0xcd 0x80 */
1212 case 0x80cd: currpers = 1; break;
1213 default:
1214 currpers = current_personality;
1215 fprintf(stderr,
1216 "Unknown syscall opcode (0x%04X) while "
1217 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001218 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001219 break;
1220 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001221# endif
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001222
H.J. Lu35be5812012-04-16 13:00:01 +02001223# ifdef X32
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001224 /* If we are built for a x32 system, then personality 0 is x32
1225 * (not x86_64), and stracing of x86_64 apps is not supported.
1226 * Stracing of i386 apps is still supported.
H.J. Lu085e4282012-04-17 11:05:04 -07001227 */
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001228 if (currpers == 0) {
1229 fprintf(stderr, "syscall_%lu(...) in unsupported "
1230 "64-bit mode of process PID=%d\n",
1231 scno, tcp->pid);
1232 return 0;
H.J. Lu35be5812012-04-16 13:00:01 +02001233 }
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001234 currpers &= ~2; /* map 2,1 to 0,1 */
H.J. Lu35be5812012-04-16 13:00:01 +02001235# endif
H.J. Lu085e4282012-04-17 11:05:04 -07001236 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001237#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001238# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001239 long psr;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001240 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001241 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001242 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001243 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001244 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001245 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001246 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001247 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001248 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001249#elif defined(AARCH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001250 switch (aarch64_io.iov_len) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001251 case sizeof(aarch64_regs):
1252 /* We are in 64-bit mode */
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001253 scno = aarch64_regs.regs[8];
1254 update_personality(tcp, 1);
1255 break;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001256 case sizeof(arm_regs):
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001257 /* We are in 32-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001258 scno = arm_regs.ARM_r7;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001259 update_personality(tcp, 0);
1260 break;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001261 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001262#elif defined(ARM)
Denys Vlasenkoe7030e52013-02-20 18:08:25 +01001263 if (arm_regs.ARM_ip != 0) {
1264 /* It is not a syscall entry */
1265 fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001266 tcp->flags |= TCB_INSYSCALL;
Denys Vlasenkoe7030e52013-02-20 18:08:25 +01001267 return 0;
1268 }
1269 /* Note: we support only 32-bit CPUs, not 26-bit */
1270
1271 if (arm_regs.ARM_cpsr & 0x20) {
1272 /* Thumb mode */
1273 scno = arm_regs.ARM_r7;
1274 } else {
1275 /* ARM mode */
1276 errno = 0;
1277 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(arm_regs.ARM_pc - 4), NULL);
1278 if (errno)
1279 return -1;
1280
1281 /* EABI syscall convention? */
1282 if (scno == 0xef000000) {
1283 scno = arm_regs.ARM_r7; /* yes */
1284 } else {
1285 if ((scno & 0x0ff00000) != 0x0f900000) {
1286 fprintf(stderr, "pid %d unknown syscall trap 0x%08lx\n",
1287 tcp->pid, scno);
1288 return -1;
1289 }
1290 /* Fixup the syscall number */
1291 scno &= 0x000fffff;
1292 }
1293 }
Denys Vlasenko7270de52013-02-21 15:46:34 +01001294
1295 scno = shuffle_scno(scno);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001296#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001297 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001298 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001299#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001300 unsigned long long regs[38];
1301
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001302 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001303 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001304 mips_a3 = regs[REG_A3];
1305 mips_r2 = regs[REG_V0];
Roland McGrath542c2c62008-05-20 01:11:56 +00001306
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001307 scno = mips_r2;
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001308 if (!SCNO_IS_VALID(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001309 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001310 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001311 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001312 return 0;
1313 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001314 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001315#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001316 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001317 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001318 if (upeek(tcp, REG_V0, &scno) < 0)
1319 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001320
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001321 if (!SCNO_IS_VALID(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001322 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001323 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001324 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001325 return 0;
1326 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001327 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001328#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001329 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001330 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001331 if (upeek(tcp, REG_R0, &scno) < 0)
1332 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001333
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001334 /*
1335 * Do some sanity checks to figure out if it's
1336 * really a syscall entry
1337 */
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001338 if (!SCNO_IS_VALID(scno)) {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001339 if (alpha_a3 == 0 || alpha_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001340 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001341 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001342 return 0;
1343 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001344 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001345#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001346 /* Disassemble the syscall trap. */
1347 /* Retrieve the syscall trap instruction. */
Denys Vlasenko46455822013-02-05 17:02:59 +01001348 unsigned long trap;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001349 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001350# if defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001351 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)sparc_regs.tpc, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001352 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001353# else
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001354 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)sparc_regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001355# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001356 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001357 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001358
1359 /* Disassemble the trap to see what personality to use. */
1360 switch (trap) {
1361 case 0x91d02010:
1362 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001363 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001364 break;
1365 case 0x91d0206d:
1366 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001367 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001368 break;
1369 case 0x91d02000:
1370 /* SunOS syscall trap. (pers 1) */
1371 fprintf(stderr, "syscall: SunOS no support\n");
1372 return -1;
1373 case 0x91d02008:
1374 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001375 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001376 break;
1377 case 0x91d02009:
1378 /* NetBSD/FreeBSD syscall trap. */
1379 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1380 return -1;
1381 case 0x91d02027:
1382 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001383 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001384 break;
1385 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001386# if defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001387 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, sparc_regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001388# else
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001389 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, sparc_regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001390# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001391 return -1;
1392 }
1393
1394 /* Extract the system call number from the registers. */
1395 if (trap == 0x91d02027)
1396 scno = 156;
1397 else
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001398 scno = sparc_regs.u_regs[U_REG_G1];
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001399 if (scno == 0) {
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001400 scno = sparc_regs.u_regs[U_REG_O0];
1401 memmove(&sparc_regs.u_regs[U_REG_O0], &sparc_regs.u_regs[U_REG_O1], 7*sizeof(sparc_regs.u_regs[0]));
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001402 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001403#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001404 if (upeek(tcp, PT_GR20, &scno) < 0)
1405 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001406#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001407 /*
1408 * In the new syscall ABI, the system call number is in R3.
1409 */
1410 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1411 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001412
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001413 if (scno < 0) {
1414 /* Odd as it may seem, a glibc bug has been known to cause
1415 glibc to issue bogus negative syscall numbers. So for
1416 our purposes, make strace print what it *should* have been */
1417 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001418 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001419 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001420 "Detected glibc bug: bogus system call"
1421 " number = %ld, correcting to %ld\n",
1422 scno,
1423 correct_scno);
1424 scno = correct_scno;
1425 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001426#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001427 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001428 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001429 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001430#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001431 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1432 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001433#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001434 int currpers;
1435 scno = tile_regs.regs[10];
1436# ifdef __tilepro__
1437 currpers = 1;
1438# else
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001439# ifndef PT_FLAGS_COMPAT
1440# define PT_FLAGS_COMPAT 0x10000 /* from Linux 3.8 on */
1441# endif
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001442 if (tile_regs.flags & PT_FLAGS_COMPAT)
1443 currpers = 1;
1444 else
1445 currpers = 0;
1446# endif
1447 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001448#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001449 if (upeek(tcp, 0, &scno) < 0)
1450 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01001451#elif defined(OR1K)
1452 scno = or1k_regs.gpr[11];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001453#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001454
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001455 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001456 return 1;
1457}
1458
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001459/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001460 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001461 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1462 * 1: ok, continue in trace_syscall_entering().
1463 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001464 * ("????" etc) and bail out.
1465 */
Roland McGratha4d48532005-06-08 20:45:28 +00001466static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001467syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001468{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001469 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001470#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001471 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001472 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001473 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1474 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001475 }
H.J. Lu35be5812012-04-16 13:00:01 +02001476#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001477 {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001478 long rax;
1479 if (x86_io.iov_len == sizeof(i386_regs)) {
1480 /* Sign extend from 32 bits */
1481 rax = (int32_t)i386_regs.eax;
1482 } else {
1483 /* Note: in X32 build, this truncates 64 to 32 bits */
1484 rax = x86_64_regs.rax;
1485 }
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001486 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001487 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001488 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1489 return 0;
1490 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001491 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001492#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001493 /* TODO: we already fetched PT_GPR2 in get_scno
1494 * and stored it in syscall_mode, reuse it here
1495 * instead of re-fetching?
1496 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001497 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001498 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001499 if (syscall_mode != -ENOSYS)
1500 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001501 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001502 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001503 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001504 return 0;
1505 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001506#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001507 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001508 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001509 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001510 if (m68k_d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001511 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001512 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", m68k_d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001513 return 0;
1514 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001515#elif defined(IA64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001516 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001517 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001518 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001519 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001520 if (ia32 && ia64_r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001521 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001522 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", ia64_r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001523 return 0;
1524 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001525#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001526 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001527 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001528 if (cris_r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001529 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001530 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", cris_r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001531 return 0;
1532 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001533#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001534 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001535 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001536 if (microblaze_r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001537 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001538 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", microblaze_r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001539 return 0;
1540 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001541#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001542 return 1;
1543}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001544
Denys Vlasenko146b9442012-03-18 22:10:48 +01001545static void
1546internal_fork(struct tcb *tcp)
1547{
1548#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1549# define ARG_FLAGS 1
1550#else
1551# define ARG_FLAGS 0
1552#endif
1553#ifndef CLONE_UNTRACED
1554# define CLONE_UNTRACED 0x00800000
1555#endif
1556 if ((ptrace_setoptions
1557 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1558 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1559 return;
1560
1561 if (!followfork)
1562 return;
1563
1564 if (entering(tcp)) {
1565 /*
1566 * We won't see the new child if clone is called with
1567 * CLONE_UNTRACED, so we keep the same logic with that option
1568 * and don't trace it.
1569 */
1570 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1571 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1572 return;
1573 setbpt(tcp);
1574 } else {
1575 if (tcp->flags & TCB_BPTSET)
1576 clearbpt(tcp);
1577 }
1578}
1579
1580#if defined(TCB_WAITEXECVE)
1581static void
1582internal_exec(struct tcb *tcp)
1583{
1584 /* Maybe we have post-execve SIGTRAP suppressed? */
1585 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1586 return; /* yes, no need to do anything */
1587
1588 if (exiting(tcp) && syserror(tcp))
1589 /* Error in execve, no post-execve SIGTRAP expected */
1590 tcp->flags &= ~TCB_WAITEXECVE;
1591 else
1592 tcp->flags |= TCB_WAITEXECVE;
1593}
1594#endif
1595
1596static void
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001597syscall_fixup_for_fork_exec(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001598{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001599 /*
1600 * We must always trace a few critical system calls in order to
1601 * correctly support following forks in the presence of tracing
1602 * qualifiers.
1603 */
1604 int (*func)();
1605
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001606 if (!SCNO_IS_VALID(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001607 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001608
1609 func = sysent[tcp->scno].sys_func;
1610
1611 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001612 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001613 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001614 ) {
1615 internal_fork(tcp);
1616 return;
1617 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001618
Denys Vlasenko84703742012-02-25 02:38:52 +01001619#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001620 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001621# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001622 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001623# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001624 ) {
1625 internal_exec(tcp);
1626 return;
1627 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001628#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001629}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001630
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001631/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001632static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001633get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001634{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001635 int i, nargs;
1636
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001637 if (SCNO_IS_VALID(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001638 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001639 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001640 nargs = tcp->u_nargs = MAX_ARGS;
1641
Denys Vlasenko523635f2012-02-25 02:44:25 +01001642#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001643 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001644 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1645 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001646#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001647 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001648 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1649 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001650#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001651 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001652 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001653 long rbs_end;
1654 /* be backwards compatible with kernel < 2.4.4... */
1655# ifndef PT_RBS_END
1656# define PT_RBS_END PT_AR_BSP
1657# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001658
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001659 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1660 return -1;
1661 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001662 return -1;
1663
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001664 sof = (cfm >> 0) & 0x7f;
1665 sol = (cfm >> 7) & 0x7f;
1666 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1667
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001668 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001669 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1670 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1671 return -1;
1672 }
1673 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001674 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1675 PT_R9 /* ECX = out1 */,
1676 PT_R10 /* EDX = out2 */,
1677 PT_R14 /* ESI = out3 */,
1678 PT_R15 /* EDI = out4 */,
1679 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001680
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001681 for (i = 0; i < nargs; ++i) {
1682 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1683 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001684 /* truncate away IVE sign-extension */
1685 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001686 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001687 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001688#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001689 /* N32 and N64 both use up to six registers. */
1690 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001691
1692 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1693 return -1;
1694
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001695 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001696 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001697# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001698 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001699# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001700 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001701#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001702 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001703 long sp;
1704
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001705 if (upeek(tcp, REG_SP, &sp) < 0)
1706 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001707 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001708 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1709 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001710 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001711 (char *)(tcp->u_arg + 4));
1712 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001713 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001714 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001715 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001716 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001717#elif defined(POWERPC)
1718# ifndef PT_ORIG_R3
1719# define PT_ORIG_R3 34
1720# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001721 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001722 if (upeek(tcp, (i==0) ?
1723 (sizeof(unsigned long) * PT_ORIG_R3) :
1724 ((i+PT_R3) * sizeof(unsigned long)),
1725 &tcp->u_arg[i]) < 0)
1726 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001727 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001728#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001729 for (i = 0; i < nargs; ++i)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001730 tcp->u_arg[i] = sparc_regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001731#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001732 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001733 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1734 return -1;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001735#elif defined(ARM) || defined(AARCH64)
1736# if defined(AARCH64)
1737 if (tcp->currpers == 1)
1738 for (i = 0; i < nargs; ++i)
1739 tcp->u_arg[i] = aarch64_regs.regs[i];
1740 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001741# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001742 for (i = 0; i < nargs; ++i)
Denys Vlasenko401374e2013-02-06 18:24:39 +01001743 tcp->u_arg[i] = arm_regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001744#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001745 (void)i;
1746 (void)nargs;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001747 tcp->u_arg[0] = avr32_regs.r12;
1748 tcp->u_arg[1] = avr32_regs.r11;
1749 tcp->u_arg[2] = avr32_regs.r10;
1750 tcp->u_arg[3] = avr32_regs.r9;
1751 tcp->u_arg[4] = avr32_regs.r5;
1752 tcp->u_arg[5] = avr32_regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001753#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001754 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 +02001755
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001756 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001757 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1758 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001759#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001760 static const int syscall_regs[MAX_ARGS] = {
1761 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1762 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001763 };
1764
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001765 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001766 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001767 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001768#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001769 int i;
1770 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001771 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001772
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001773 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001774 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1775 return -1;
Denys Vlasenko6cf36052013-02-15 15:01:38 +01001776#elif defined(I386)
1777 (void)i;
1778 (void)nargs;
1779 tcp->u_arg[0] = i386_regs.ebx;
1780 tcp->u_arg[1] = i386_regs.ecx;
1781 tcp->u_arg[2] = i386_regs.edx;
1782 tcp->u_arg[3] = i386_regs.esi;
1783 tcp->u_arg[4] = i386_regs.edi;
1784 tcp->u_arg[5] = i386_regs.ebp;
H.J. Lu35be5812012-04-16 13:00:01 +02001785#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001786 (void)i;
1787 (void)nargs;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001788 if (x86_io.iov_len != sizeof(i386_regs)) {
1789 /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001790 tcp->u_arg[0] = x86_64_regs.rdi;
1791 tcp->u_arg[1] = x86_64_regs.rsi;
1792 tcp->u_arg[2] = x86_64_regs.rdx;
1793 tcp->u_arg[3] = x86_64_regs.r10;
1794 tcp->u_arg[4] = x86_64_regs.r8;
1795 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001796# ifdef X32
1797 tcp->ext_arg[0] = x86_64_regs.rdi;
1798 tcp->ext_arg[1] = x86_64_regs.rsi;
1799 tcp->ext_arg[2] = x86_64_regs.rdx;
1800 tcp->ext_arg[3] = x86_64_regs.r10;
1801 tcp->ext_arg[4] = x86_64_regs.r8;
1802 tcp->ext_arg[5] = x86_64_regs.r9;
1803# endif
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001804 } else {
1805 /* i386 ABI */
Denys Vlasenko6cf36052013-02-15 15:01:38 +01001806 /* Zero-extend from 32 bits */
1807 /* Use widen_to_long(tcp->u_arg[N]) in syscall handlers
1808 * if you need to use *sign-extended* parameter.
1809 */
1810 tcp->u_arg[0] = (long)(uint32_t)i386_regs.ebx;
1811 tcp->u_arg[1] = (long)(uint32_t)i386_regs.ecx;
1812 tcp->u_arg[2] = (long)(uint32_t)i386_regs.edx;
1813 tcp->u_arg[3] = (long)(uint32_t)i386_regs.esi;
1814 tcp->u_arg[4] = (long)(uint32_t)i386_regs.edi;
1815 tcp->u_arg[5] = (long)(uint32_t)i386_regs.ebp;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001816 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001817#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001818 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001819 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1820 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001821#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001822 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001823 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001824 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001825 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001826
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001827 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001828 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1829 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001830#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001831 for (i = 0; i < nargs; ++i)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001832 tcp->u_arg[i] = tile_regs.regs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001833#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001834 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001835 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1836 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01001837#elif defined(OR1K)
1838 (void)nargs;
1839 for (i = 0; i < 6; ++i)
1840 tcp->u_arg[i] = or1k_regs.gpr[3 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001841#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001842 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001843 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1844 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001845#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001846 return 1;
1847}
1848
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001849static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001850trace_syscall_entering(struct tcb *tcp)
1851{
1852 int res, scno_good;
1853
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001854#if defined TCB_WAITEXECVE
1855 if (tcp->flags & TCB_WAITEXECVE) {
1856 /* This is the post-execve SIGTRAP. */
1857 tcp->flags &= ~TCB_WAITEXECVE;
1858 return 0;
1859 }
1860#endif
1861
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001862 scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001863 if (res == 0)
1864 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001865 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001866 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001867 if (res == 0)
1868 return res;
1869 if (res == 1)
1870 res = get_syscall_args(tcp);
1871 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001872
1873 if (res != 1) {
1874 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001875 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001876 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001877 else if (!SCNO_IS_VALID(tcp->scno))
Denys Vlasenko7270de52013-02-21 15:46:34 +01001878 tprintf("%s(", undefined_scno_name(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001879 else
1880 tprintf("%s(", sysent[tcp->scno].sys_name);
1881 /*
1882 * " <unavailable>" will be added later by the code which
1883 * detects ptrace errors.
1884 */
1885 goto ret;
1886 }
1887
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001888#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001889 while (SCNO_IS_VALID(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001890# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001891 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001892 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001893 break;
1894 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001895# endif
1896# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001897 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001898 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001899 break;
1900 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001901# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001902 break;
1903 }
1904#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1905
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001906 if (need_fork_exec_workarounds)
1907 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001908
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001909 if ((SCNO_IS_VALID(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001910 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1911 (tracing_paths && !pathtrace_match(tcp))) {
1912 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1913 return 0;
1914 }
1915
1916 tcp->flags &= ~TCB_FILTERED;
1917
1918 if (cflag == CFLAG_ONLY_STATS) {
1919 res = 0;
1920 goto ret;
1921 }
1922
1923 printleader(tcp);
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001924 if (!SCNO_IS_VALID(tcp->scno))
Denys Vlasenko7270de52013-02-21 15:46:34 +01001925 tprintf("%s(", undefined_scno_name(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001926 else
1927 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001928 if (!SCNO_IS_VALID(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001929 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1930 sysent[tcp->scno].sys_func != sys_exit))
1931 res = printargs(tcp);
1932 else
1933 res = (*sysent[tcp->scno].sys_func)(tcp);
1934
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001935 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001936 ret:
1937 tcp->flags |= TCB_INSYSCALL;
1938 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001939 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001940 gettimeofday(&tcp->etime, NULL);
1941 return res;
1942}
1943
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001944/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001945 * 1: ok, continue in trace_syscall_exiting().
1946 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001947 * ("????" etc) and bail out.
1948 */
1949static int
1950get_syscall_result(struct tcb *tcp)
1951{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001952#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001953 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1954 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001955#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001956# define SO_MASK 0x10000000
1957 {
1958 long flags;
1959 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1960 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001961 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001962 return -1;
1963 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001964 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001965 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001966#elif defined(AVR32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001967 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001968#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001969 if (upeek(tcp, PT_R0, &bfin_r0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001970 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001971#elif defined(I386)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001972 /* already done by get_regs */
H.J. Lu35be5812012-04-16 13:00:01 +02001973#elif defined(X86_64) || defined(X32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001974 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001975#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001976# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001977 long psr;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001978 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1979 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001980 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001981 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001982 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001983 return -1;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001984#elif defined(ARM)
1985 /* already done by get_regs */
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001986#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001987 /* register reading already done by get_regs */
1988
1989 /* Used to do this, but we did it on syscall entry already: */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001990 /* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
1991 * else it's personality 0.
1992 */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001993 /*update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));*/
Denys Vlasenko523635f2012-02-25 02:44:25 +01001994#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001995 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001996 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001997#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001998 unsigned long long regs[38];
1999
2000 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
2001 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002002 mips_a3 = regs[REG_A3];
2003 mips_r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01002004#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002005 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002006 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002007 if (upeek(tcp, REG_V0, &mips_r2) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002008 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002009#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002010 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002011 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002012 if (upeek(tcp, REG_R0, &alpha_r0) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002013 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002014#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002015 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002016#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002017 if (upeek(tcp, PT_GR28, &hppa_r28) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002018 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002019#elif defined(SH)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002020 /* new syscall ABI returns result in R0 */
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002021 if (upeek(tcp, 4*REG_REG0, (long *)&sh_r0) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002022 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002023#elif defined(SH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002024 /* ABI defines result returned in r9 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002025 if (upeek(tcp, REG_GENERAL(9), (long *)&sh64_r9) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002026 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002027#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002028 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002029 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002030#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002031 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002032#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002033 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002034 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01002035#elif defined(OR1K)
2036 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002037#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002038 return 1;
2039}
2040
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002041/* Called at each syscall exit */
2042static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002043syscall_fixup_on_sysexit(struct tcb *tcp)
2044{
Denys Vlasenko523635f2012-02-25 02:44:25 +01002045#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002046 if (syscall_mode != -ENOSYS)
2047 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02002048 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002049 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
2050 /*
2051 * Return from execve.
2052 * Fake a return value of zero. We leave the TCB_WAITEXECVE
2053 * flag set for the post-execve SIGTRAP to see and reset.
2054 */
2055 gpr2 = 0;
2056 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002057#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002058}
2059
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002060/*
2061 * Check the syscall return value register value for whether it is
2062 * a negated errno code indicating an error, or a success return value.
2063 */
2064static inline int
2065is_negated_errno(unsigned long int val)
2066{
2067 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko2544f982013-02-19 17:39:56 +01002068#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01002069 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002070 val = (unsigned int) val;
2071 max = (unsigned int) max;
2072 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002073#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002074 return val > max;
2075}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002076
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002077#if defined(X32)
2078static inline int
2079is_negated_errno_x32(unsigned long long val)
2080{
2081 unsigned long long max = -(long long) nerrnos;
2082 /*
2083 * current_wordsize is 4 even in personality 0 (native X32)
2084 * but truncation _must not_ be done in it.
2085 * can't check current_wordsize here!
2086 */
2087 if (current_personality != 0) {
2088 val = (uint32_t) val;
2089 max = (uint32_t) max;
2090 }
2091 return val > max;
2092}
2093#endif
2094
Denys Vlasenko907735a2012-03-21 00:23:16 +01002095/* Returns:
2096 * 1: ok, continue in trace_syscall_exiting().
2097 * -1: error, trace_syscall_exiting() should print error indicator
2098 * ("????" etc) and bail out.
2099 */
Denys Vlasenkoc956ef02013-02-16 14:25:56 +01002100static void
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002101get_error(struct tcb *tcp)
2102{
2103 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002104 int check_errno = 1;
Denys Vlasenkoc956ef02013-02-16 14:25:56 +01002105 if (SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01002106 && (sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS)
2107 ) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002108 check_errno = 0;
2109 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002110#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002111 if (check_errno && is_negated_errno(gpr2)) {
2112 tcp->u_rval = -1;
2113 u_error = -gpr2;
2114 }
2115 else {
2116 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002117 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002118#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002119 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002120 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002121 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002122 }
2123 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002124 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002125 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002126#elif defined(X86_64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002127 long rax;
2128 if (x86_io.iov_len == sizeof(i386_regs)) {
2129 /* Sign extend from 32 bits */
2130 rax = (int32_t)i386_regs.eax;
2131 } else {
2132 rax = x86_64_regs.rax;
2133 }
2134 if (check_errno && is_negated_errno(rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002135 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002136 u_error = -rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002137 }
2138 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002139 tcp->u_rval = rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002140 }
2141#elif defined(X32)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002142 /* In X32, return value is 64-bit (llseek uses one).
2143 * Using merely "long rax" would not work.
2144 */
2145 long long rax;
2146 if (x86_io.iov_len == sizeof(i386_regs)) {
2147 /* Sign extend from 32 bits */
2148 rax = (int32_t)i386_regs.eax;
2149 } else {
2150 rax = x86_64_regs.rax;
2151 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002152 /* Careful: is_negated_errno() works only on longs */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002153 if (check_errno && is_negated_errno_x32(rax)) {
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002154 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002155 u_error = -rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002156 }
2157 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002158 tcp->u_rval = rax; /* truncating */
2159 tcp->u_lrval = rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002160 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002161#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002162 if (ia32) {
2163 int err;
2164
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002165 err = (int)ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002166 if (check_errno && is_negated_errno(err)) {
2167 tcp->u_rval = -1;
2168 u_error = -err;
2169 }
2170 else {
2171 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002172 }
2173 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002174 if (check_errno && ia64_r10) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002175 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002176 u_error = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002177 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002178 tcp->u_rval = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002179 }
2180 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002181#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002182 if (check_errno && mips_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002183 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002184 u_error = mips_r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002185 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002186 tcp->u_rval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002187# if defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002188 tcp->u_lrval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002189# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002190 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002191#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002192 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002193 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002194 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002195 }
2196 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002197 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002198 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002199#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002200 if (check_errno && is_negated_errno(m68k_d0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002201 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002202 u_error = -m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002203 }
2204 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002205 tcp->u_rval = m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002206 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002207#elif defined(ARM) || defined(AARCH64)
2208# if defined(AARCH64)
2209 if (tcp->currpers == 1) {
2210 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2211 tcp->u_rval = -1;
2212 u_error = -aarch64_regs.regs[0];
2213 }
2214 else {
2215 tcp->u_rval = aarch64_regs.regs[0];
2216 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002217 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002218 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01002219# endif
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002220 {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002221 if (check_errno && is_negated_errno(arm_regs.ARM_r0)) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002222 tcp->u_rval = -1;
Denys Vlasenko401374e2013-02-06 18:24:39 +01002223 u_error = -arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002224 }
2225 else {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002226 tcp->u_rval = arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002227 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002228 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002229#elif defined(AVR32)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002230 if (check_errno && avr32_regs.r12 && (unsigned) -avr32_regs.r12 < nerrnos) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002231 tcp->u_rval = -1;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002232 u_error = -avr32_regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002233 }
2234 else {
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002235 tcp->u_rval = avr32_regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002236 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002237#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002238 if (check_errno && is_negated_errno(bfin_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002239 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002240 u_error = -bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002241 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002242 tcp->u_rval = bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002243 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002244#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002245 if (check_errno && alpha_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002246 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002247 u_error = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002248 }
2249 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002250 tcp->u_rval = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002251 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002252#elif defined(SPARC)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002253 if (check_errno && sparc_regs.psr & PSR_C) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002254 tcp->u_rval = -1;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002255 u_error = sparc_regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002256 }
2257 else {
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002258 tcp->u_rval = sparc_regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002259 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002260#elif defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002261 if (check_errno && sparc_regs.tstate & 0x1100000000UL) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002262 tcp->u_rval = -1;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002263 u_error = sparc_regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002264 }
2265 else {
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002266 tcp->u_rval = sparc_regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002267 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002268#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002269 if (check_errno && is_negated_errno(hppa_r28)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002270 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002271 u_error = -hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002272 }
2273 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002274 tcp->u_rval = hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002275 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002276#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002277 if (check_errno && is_negated_errno(sh_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002278 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002279 u_error = -sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002280 }
2281 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002282 tcp->u_rval = sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002283 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002284#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002285 if (check_errno && is_negated_errno(sh64_r9)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002286 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002287 u_error = -sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002288 }
2289 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002290 tcp->u_rval = sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002291 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002292#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002293 if (check_errno && cris_r10 && (unsigned) -cris_r10 < nerrnos) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002294 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002295 u_error = -cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002296 }
2297 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002298 tcp->u_rval = cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002299 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002300#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002301 /*
2302 * The standard tile calling convention returns the value (or negative
2303 * errno) in r0, and zero (or positive errno) in r1.
2304 * Until at least kernel 3.8, however, the r1 value is not reflected
2305 * in ptregs at this point, so we use r0 here.
2306 */
2307 if (check_errno && is_negated_errno(tile_regs.regs[0])) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002308 tcp->u_rval = -1;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002309 u_error = -tile_regs.regs[0];
2310 } else {
2311 tcp->u_rval = tile_regs.regs[0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002312 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002313#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002314 if (check_errno && is_negated_errno(microblaze_r3)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002315 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002316 u_error = -microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002317 }
2318 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002319 tcp->u_rval = microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002320 }
Christian Svensson492f81f2013-02-14 13:26:27 +01002321#elif defined(OR1K)
2322 if (check_errno && is_negated_errno(or1k_regs.gpr[11])) {
2323 tcp->u_rval = -1;
2324 u_error = -or1k_regs.gpr[11];
2325 }
2326 else {
2327 tcp->u_rval = or1k_regs.gpr[11];
2328 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002329#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002330 tcp->u_error = u_error;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002331}
2332
2333static void
2334dumpio(struct tcb *tcp)
2335{
2336 if (syserror(tcp))
2337 return;
2338 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
2339 return;
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01002340 if (!SCNO_IS_VALID(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002341 return;
2342 if (sysent[tcp->scno].sys_func == printargs)
2343 return;
2344 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
2345 if (sysent[tcp->scno].sys_func == sys_read ||
2346 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002347 sysent[tcp->scno].sys_func == sys_recv ||
2348 sysent[tcp->scno].sys_func == sys_recvfrom)
2349 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
2350 else if (sysent[tcp->scno].sys_func == sys_readv)
2351 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2352 return;
2353 }
2354 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
2355 if (sysent[tcp->scno].sys_func == sys_write ||
2356 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002357 sysent[tcp->scno].sys_func == sys_send ||
2358 sysent[tcp->scno].sys_func == sys_sendto)
2359 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
2360 else if (sysent[tcp->scno].sys_func == sys_writev)
2361 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2362 return;
2363 }
2364}
2365
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002366static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002367trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002368{
2369 int sys_res;
2370 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002371 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002372 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002373
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002374 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002375 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002376 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002377
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002378#if SUPPORTED_PERSONALITIES > 1
2379 update_personality(tcp, tcp->currpers);
2380#endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002381 res = (get_regs_error ? -1 : get_syscall_result(tcp));
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002382 if (res == 1) {
2383 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenkoc956ef02013-02-16 14:25:56 +01002384 get_error(tcp); /* never fails */
2385 if (need_fork_exec_workarounds)
2386 syscall_fixup_for_fork_exec(tcp);
2387 if (filtered(tcp))
2388 goto ret;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002389 }
2390
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002391 if (cflag) {
2392 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002393 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002394 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002395 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002396 }
2397 }
2398
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002399 /* If not in -ff mode, and printing_tcp != tcp,
2400 * then the log currently does not end with output
2401 * of _our syscall entry_, but with something else.
2402 * We need to say which syscall's return is this.
2403 *
2404 * Forced reprinting via TCB_REPRINT is used only by
2405 * "strace -ff -oLOG test/threaded_execve" corner case.
2406 * It's the only case when -ff mode needs reprinting.
2407 */
2408 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2409 tcp->flags &= ~TCB_REPRINT;
2410 printleader(tcp);
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01002411 if (!SCNO_IS_VALID(tcp->scno))
Denys Vlasenko7270de52013-02-21 15:46:34 +01002412 tprintf("<... %s resumed> ", undefined_scno_name(tcp));
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002413 else
2414 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2415 }
2416 printing_tcp = tcp;
2417
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002418 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002419 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002420 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002421 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002422 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002423 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002424 tcp->flags &= ~TCB_INSYSCALL;
2425 return res;
2426 }
2427
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002428 sys_res = 0;
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01002429 if (!SCNO_IS_VALID(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002430 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002431 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002432 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002433 /* FIXME: not_failing_only (IOW, option -z) is broken:
2434 * failure of syscall is known only after syscall return.
2435 * Thus we end up with something like this on, say, ENOENT:
2436 * open("doesnt_exist", O_RDONLY <unfinished ...>
2437 * {next syscall decode}
2438 * whereas the intended result is that open(...) line
2439 * is not shown at all.
2440 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002441 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002442 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002443 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2444 }
2445
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002446 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002447 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002448 u_error = tcp->u_error;
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01002449 if (!SCNO_IS_VALID(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002450 qual_flags[tcp->scno] & QUAL_RAW) {
2451 if (u_error)
2452 tprintf("= -1 (errno %ld)", u_error);
2453 else
2454 tprintf("= %#lx", tcp->u_rval);
2455 }
2456 else if (!(sys_res & RVAL_NONE) && u_error) {
2457 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002458 /* Blocked signals do not interrupt any syscalls.
2459 * In this case syscalls don't return ERESTARTfoo codes.
2460 *
2461 * Deadly signals set to SIG_DFL interrupt syscalls
2462 * and kill the process regardless of which of the codes below
2463 * is returned by the interrupted syscall.
2464 * In some cases, kernel forces a kernel-generated deadly
2465 * signal to be unblocked and set to SIG_DFL (and thus cause
2466 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2467 * or SIGILL. (The alternative is to leave process spinning
2468 * forever on the faulty instruction - not useful).
2469 *
2470 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2471 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2472 * but kernel will always restart them.
2473 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002474 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002475 /* Most common type of signal-interrupted syscall exit code.
2476 * The system call will be restarted with the same arguments
2477 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2478 */
2479 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002480 break;
2481 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002482 /* Rare. For example, fork() returns this if interrupted.
2483 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2484 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002485 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002486 break;
2487 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002488 /* pause(), rt_sigsuspend() etc use this code.
2489 * SA_RESTART is ignored (assumed not set):
2490 * syscall won't restart (will return EINTR instead)
Denys Vlasenko30c03232013-02-19 16:59:26 +01002491 * even after signal with SA_RESTART set. However,
2492 * after SIG_IGN or SIG_DFL signal it will restart
2493 * (thus the name "restart only if has no handler").
Denys Vlasenkofe585652012-01-12 11:26:34 +01002494 */
2495 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002496 break;
2497 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002498 /* Syscalls like nanosleep(), poll() which can't be
2499 * restarted with their original arguments use this
2500 * code. Kernel will execute restart_syscall() instead,
2501 * which changes arguments before restarting syscall.
2502 * SA_RESTART is ignored (assumed not set) similarly
2503 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2504 * since restart data is saved in "restart block"
2505 * in task struct, and if signal handler uses a syscall
2506 * which in turn saves another such restart block,
2507 * old data is lost and restart becomes impossible)
2508 */
2509 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002510 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002511 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002512 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002513 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002514 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002515 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002516 strerror(u_error));
2517 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002518 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002519 strerror(u_error));
2520 break;
2521 }
2522 if ((sys_res & RVAL_STR) && tcp->auxstr)
2523 tprintf(" (%s)", tcp->auxstr);
2524 }
2525 else {
2526 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002527 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002528 else {
2529 switch (sys_res & RVAL_MASK) {
2530 case RVAL_HEX:
2531 tprintf("= %#lx", tcp->u_rval);
2532 break;
2533 case RVAL_OCTAL:
2534 tprintf("= %#lo", tcp->u_rval);
2535 break;
2536 case RVAL_UDECIMAL:
2537 tprintf("= %lu", tcp->u_rval);
2538 break;
2539 case RVAL_DECIMAL:
2540 tprintf("= %ld", tcp->u_rval);
2541 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002542#if defined(LINUX_MIPSN32) || defined(X32)
2543 /*
2544 case RVAL_LHEX:
2545 tprintf("= %#llx", tcp->u_lrval);
2546 break;
2547 case RVAL_LOCTAL:
2548 tprintf("= %#llo", tcp->u_lrval);
2549 break;
2550 */
2551 case RVAL_LUDECIMAL:
2552 tprintf("= %llu", tcp->u_lrval);
2553 break;
2554 /*
2555 case RVAL_LDECIMAL:
2556 tprintf("= %lld", tcp->u_lrval);
2557 break;
2558 */
2559#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002560 default:
2561 fprintf(stderr,
2562 "invalid rval format\n");
2563 break;
2564 }
2565 }
2566 if ((sys_res & RVAL_STR) && tcp->auxstr)
2567 tprintf(" (%s)", tcp->auxstr);
2568 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002569 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002570 tv_sub(&tv, &tv, &tcp->etime);
2571 tprintf(" <%ld.%06ld>",
2572 (long) tv.tv_sec, (long) tv.tv_usec);
2573 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002574 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002575 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002576 line_ended();
2577
Denys Vlasenko3b738812011-08-22 02:06:35 +02002578 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002579 tcp->flags &= ~TCB_INSYSCALL;
2580 return 0;
2581}
2582
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002583int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002584trace_syscall(struct tcb *tcp)
2585{
2586 return exiting(tcp) ?
2587 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2588}