blob: 5c0d5808939c846d432bbf50adbdca4ab8185d06 [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
902#ifndef get_regs
903long get_regs_error;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100904void
905get_regs(pid_t pid)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100906{
907# if defined(AVR32)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100908 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &avr32_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100909# elif defined(I386)
910 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &i386_regs);
911# elif defined(X86_64) || defined(X32)
Denys Vlasenkoe3b248d2013-02-15 00:24:19 +0100912 /*
913 * PTRACE_GETREGSET was introduced in 2.6.33.
914 * Let's be paranoid and require a bit later kernel.
915 */
916 if (os_release >= KERNEL_VERSION(2,6,35)) {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100917 /*x86_io.iov_base = &x86_regs_union; - already is */
918 x86_io.iov_len = sizeof(x86_regs_union);
919 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (long) &x86_io);
920 } else {
921 /* Use old method, with heuristical detection of 32-bitness */
922 x86_io.iov_len = sizeof(x86_64_regs);
923 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &x86_64_regs);
924 if (!get_regs_error && x86_64_regs.cs == 0x23) {
925 x86_io.iov_len = sizeof(i386_regs);
926 /*
927 * The order is important: i386_regs and x86_64_regs
928 * are overlaid in memory!
929 */
930 i386_regs.ebx = x86_64_regs.rbx;
931 i386_regs.ecx = x86_64_regs.rcx;
932 i386_regs.edx = x86_64_regs.rdx;
933 i386_regs.esi = x86_64_regs.rsi;
934 i386_regs.edi = x86_64_regs.rdi;
935 i386_regs.ebp = x86_64_regs.rbp;
936 i386_regs.eax = x86_64_regs.rax;
937 /*i386_regs.xds = x86_64_regs.ds; unused by strace */
938 /*i386_regs.xes = x86_64_regs.es; ditto... */
939 /*i386_regs.xfs = x86_64_regs.fs;*/
940 /*i386_regs.xgs = x86_64_regs.gs;*/
941 i386_regs.orig_eax = x86_64_regs.orig_rax;
942 i386_regs.eip = x86_64_regs.rip;
943 /*i386_regs.xcs = x86_64_regs.cs;*/
944 /*i386_regs.eflags = x86_64_regs.eflags;*/
945 i386_regs.esp = x86_64_regs.rsp;
946 /*i386_regs.xss = x86_64_regs.ss;*/
947 }
948 }
Denys Vlasenko401374e2013-02-06 18:24:39 +0100949# elif defined(ARM)
950 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (void *)&arm_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100951# elif defined(AARCH64)
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100952 /*aarch64_io.iov_base = &arm_regs_union; - already is */
953 aarch64_io.iov_len = sizeof(arm_regs_union);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100954 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void *)&aarch64_io);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100955# if 0
956 /* Paranoia checks */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100957 if (get_regs_error)
958 return;
959 switch (aarch64_io.iov_len) {
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100960 case sizeof(aarch64_regs):
961 /* We are in 64-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100962 break;
963 case sizeof(arm_regs):
964 /* We are in 32-bit mode */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100965 break;
966 default:
967 get_regs_error = -1;
968 break;
969 }
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100970# endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100971# elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100972 get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&sparc_regs, 0);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100973# elif defined(TILE)
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500974 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &tile_regs);
Christian Svensson492f81f2013-02-14 13:26:27 +0100975# elif defined(OR1K)
976 or1k_io.iov_len = sizeof(or1k_regs);
977 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &or1k_io);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100978# endif
979}
980#endif
981
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200982/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100983 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
984 * 1: ok, continue in trace_syscall_entering().
985 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200986 * ("????" etc) and bail out.
987 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100988static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200989get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000990{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000991 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000992
Denys Vlasenko523635f2012-02-25 02:44:25 +0100993#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000994 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200995 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000996
997 if (syscall_mode != -ENOSYS) {
998 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000999 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +00001000 */
1001 scno = syscall_mode;
1002 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001003 /*
Michal Ludvig882eda82002-11-11 12:50:47 +00001004 * Old style of "passing" the scno via the SVC instruction.
1005 */
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001006 long psw;
Michal Ludvig882eda82002-11-11 12:50:47 +00001007 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001008 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +02001009 static const int gpr_offset[16] = {
1010 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
1011 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
1012 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
1013 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
1014 };
Roland McGrath761b5d72002-12-15 23:58:31 +00001015
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001016 if (upeek(tcp, PT_PSWADDR, &psw) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +00001017 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +00001018 errno = 0;
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001019 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(psw - sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +00001020 if (errno) {
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001021 perror_msg("%s", "peektext(psw-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +00001022 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +00001023 }
Michal Ludvig882eda82002-11-11 12:50:47 +00001024
1025 /*
1026 * We have to check if the SVC got executed directly or via an
1027 * EXECUTE instruction. In case of EXECUTE it is necessary to do
1028 * instruction decoding to derive the system call number.
1029 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
1030 * so that this doesn't work if a SVC opcode is part of an EXECUTE
1031 * opcode. Since there is no way to find out the opcode size this
1032 * is the best we can do...
1033 */
Michal Ludvig882eda82002-11-11 12:50:47 +00001034 if ((opcode & 0xff00) == 0x0a00) {
1035 /* SVC opcode */
1036 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +00001037 }
Michal Ludvig882eda82002-11-11 12:50:47 +00001038 else {
1039 /* SVC got executed by EXECUTE instruction */
1040
1041 /*
1042 * Do instruction decoding of EXECUTE. If you really want to
1043 * understand this, read the Principles of Operations.
1044 */
1045 svc_addr = (void *) (opcode & 0xfff);
1046
1047 tmp = 0;
1048 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001049 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001050 return -1;
1051 svc_addr += tmp;
1052
1053 tmp = 0;
1054 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001055 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001056 return -1;
1057 svc_addr += tmp;
1058
Denys Vlasenkofb036672009-01-23 16:30:26 +00001059 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +00001060 if (errno)
1061 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001062# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +00001063 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001064# else
Michal Ludvig882eda82002-11-11 12:50:47 +00001065 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001066# endif
Michal Ludvig882eda82002-11-11 12:50:47 +00001067 tmp = 0;
1068 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001069 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001070 return -1;
1071
1072 scno = (scno | tmp) & 0xff;
1073 }
1074 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001075#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001076 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001077 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001078# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001079 /* TODO: speed up strace by not doing this at every syscall.
1080 * We only need to do it after execve.
1081 */
1082 int currpers;
1083 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +02001084
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001085 /* Check for 64/32 bit mode. */
1086 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
1087 return -1;
1088 /* SF is bit 0 of MSR */
1089 if (val < 0)
1090 currpers = 0;
1091 else
1092 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001093 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001094# endif
1095#elif defined(AVR32)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001096 scno = avr32_regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001097#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001098 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001099 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001100#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001101 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +02001102#elif defined(X86_64) || defined(X32)
1103# ifndef __X32_SYSCALL_BIT
1104# define __X32_SYSCALL_BIT 0x40000000
1105# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001106 int currpers;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001107# if 1
1108 /* GETREGSET of NT_PRSTATUS tells us regset size,
1109 * which unambiguously detects i386.
1110 *
1111 * Linux kernel distinguishes x86-64 and x32 processes
1112 * solely by looking at __X32_SYSCALL_BIT:
1113 * arch/x86/include/asm/compat.h::is_x32_task():
1114 * if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)
1115 * return true;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001116 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001117 if (x86_io.iov_len == sizeof(i386_regs)) {
1118 scno = i386_regs.orig_eax;
1119 currpers = 1;
1120 } else {
1121 scno = x86_64_regs.orig_rax;
1122 currpers = 0;
1123 if (scno & __X32_SYSCALL_BIT) {
1124 scno -= __X32_SYSCALL_BIT;
1125 currpers = 2;
1126 }
1127 }
1128# elif 0
1129 /* cs = 0x33 for long mode (native 64 bit and x32)
1130 * cs = 0x23 for compatibility mode (32 bit)
1131 * ds = 0x2b for x32 mode (x86-64 in 32 bit)
1132 */
1133 scno = x86_64_regs.orig_rax;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001134 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001135 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +02001136 case 0x33:
1137 if (x86_64_regs.ds == 0x2b) {
1138 currpers = 2;
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001139 scno &= ~__X32_SYSCALL_BIT;
H.J. Lu35be5812012-04-16 13:00:01 +02001140 } else
1141 currpers = 0;
1142 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001143 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001144 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001145 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001146 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001147 currpers = current_personality;
1148 break;
1149 }
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001150# elif 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001151 /* This version analyzes the opcode of a syscall instruction.
1152 * (int 0x80 on i386 vs. syscall on x86-64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001153 * It works, but is too complicated, and strictly speaking, unreliable.
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001154 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001155 unsigned long call, rip = x86_64_regs.rip;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001156 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
1157 rip -= 2;
1158 errno = 0;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001159 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001160 if (errno)
1161 fprintf(stderr, "ptrace_peektext failed: %s\n",
1162 strerror(errno));
1163 switch (call & 0xffff) {
1164 /* x86-64: syscall = 0x0f 0x05 */
1165 case 0x050f: currpers = 0; break;
1166 /* i386: int 0x80 = 0xcd 0x80 */
1167 case 0x80cd: currpers = 1; break;
1168 default:
1169 currpers = current_personality;
1170 fprintf(stderr,
1171 "Unknown syscall opcode (0x%04X) while "
1172 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001173 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001174 break;
1175 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001176# endif
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001177
H.J. Lu35be5812012-04-16 13:00:01 +02001178# ifdef X32
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001179 /* If we are built for a x32 system, then personality 0 is x32
1180 * (not x86_64), and stracing of x86_64 apps is not supported.
1181 * Stracing of i386 apps is still supported.
H.J. Lu085e4282012-04-17 11:05:04 -07001182 */
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001183 if (currpers == 0) {
1184 fprintf(stderr, "syscall_%lu(...) in unsupported "
1185 "64-bit mode of process PID=%d\n",
1186 scno, tcp->pid);
1187 return 0;
H.J. Lu35be5812012-04-16 13:00:01 +02001188 }
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001189 currpers &= ~2; /* map 2,1 to 0,1 */
H.J. Lu35be5812012-04-16 13:00:01 +02001190# endif
H.J. Lu085e4282012-04-17 11:05:04 -07001191 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001192#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001193# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001194 long psr;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001195 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001196 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001197 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001198 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001199 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001200 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001201 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001202 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001203 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001204#elif defined(AARCH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001205 switch (aarch64_io.iov_len) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001206 case sizeof(aarch64_regs):
1207 /* We are in 64-bit mode */
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001208 scno = aarch64_regs.regs[8];
1209 update_personality(tcp, 1);
1210 break;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001211 case sizeof(arm_regs):
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001212 /* We are in 32-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001213 scno = arm_regs.ARM_r7;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001214 update_personality(tcp, 0);
1215 break;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001216 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001217#elif defined(ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001218 /*
1219 * We only need to grab the syscall number on syscall entry.
1220 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001221 if (arm_regs.ARM_ip == 0) {
Roland McGrath0f87c492003-06-03 23:29:04 +00001222 /*
Denys Vlasenko401374e2013-02-06 18:24:39 +01001223 * Note: we only deal with 32-bit CPUs here
Roland McGrath0f87c492003-06-03 23:29:04 +00001224 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001225 if (arm_regs.ARM_cpsr & 0x20) {
Roland McGrath0f87c492003-06-03 23:29:04 +00001226 /*
1227 * Get the Thumb-mode system call number
1228 */
Denys Vlasenko401374e2013-02-06 18:24:39 +01001229 scno = arm_regs.ARM_r7;
Roland McGrath0f87c492003-06-03 23:29:04 +00001230 } else {
1231 /*
1232 * Get the ARM-mode system call number
1233 */
1234 errno = 0;
Denys Vlasenko401374e2013-02-06 18:24:39 +01001235 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(arm_regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +00001236 if (errno)
1237 return -1;
1238
Roland McGrathf691bd22006-04-25 07:34:41 +00001239 /* Handle the EABI syscall convention. We do not
1240 bother converting structures between the two
1241 ABIs, but basic functionality should work even
1242 if strace and the traced program have different
1243 ABIs. */
1244 if (scno == 0xef000000) {
Denys Vlasenko401374e2013-02-06 18:24:39 +01001245 scno = arm_regs.ARM_r7;
Roland McGrathf691bd22006-04-25 07:34:41 +00001246 } else {
1247 if ((scno & 0x0ff00000) != 0x0f900000) {
1248 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1249 scno);
1250 return -1;
1251 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001252
Roland McGrathf691bd22006-04-25 07:34:41 +00001253 /*
1254 * Fixup the syscall number
1255 */
1256 scno &= 0x000fffff;
1257 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001258 }
Roland McGrath56703312008-05-20 01:35:55 +00001259 if (scno & 0x0f0000) {
1260 /*
1261 * Handle ARM specific syscall
1262 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001263 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +00001264 scno &= 0x0000ffff;
1265 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001266 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001267
Roland McGrath0f87c492003-06-03 23:29:04 +00001268 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001269 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1270 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001271 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001272#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001273 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001274 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001275#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001276 unsigned long long regs[38];
1277
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001278 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001279 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001280 mips_a3 = regs[REG_A3];
1281 mips_r2 = regs[REG_V0];
Roland McGrath542c2c62008-05-20 01:11:56 +00001282
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001283 scno = mips_r2;
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001284 if (!SCNO_IS_VALID(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001285 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001286 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001287 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001288 return 0;
1289 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001290 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001291#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001292 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001293 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001294 if (upeek(tcp, REG_V0, &scno) < 0)
1295 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001296
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001297 if (!SCNO_IS_VALID(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001298 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001299 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001300 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001301 return 0;
1302 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001303 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001304#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001305 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001306 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001307 if (upeek(tcp, REG_R0, &scno) < 0)
1308 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001309
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001310 /*
1311 * Do some sanity checks to figure out if it's
1312 * really a syscall entry
1313 */
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001314 if (!SCNO_IS_VALID(scno)) {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001315 if (alpha_a3 == 0 || alpha_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001316 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001317 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001318 return 0;
1319 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001320 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001321#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001322 /* Disassemble the syscall trap. */
1323 /* Retrieve the syscall trap instruction. */
Denys Vlasenko46455822013-02-05 17:02:59 +01001324 unsigned long trap;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001325 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001326# if defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001327 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)sparc_regs.tpc, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001328 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001329# else
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001330 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)sparc_regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001331# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001332 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001333 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001334
1335 /* Disassemble the trap to see what personality to use. */
1336 switch (trap) {
1337 case 0x91d02010:
1338 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001339 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001340 break;
1341 case 0x91d0206d:
1342 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001343 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001344 break;
1345 case 0x91d02000:
1346 /* SunOS syscall trap. (pers 1) */
1347 fprintf(stderr, "syscall: SunOS no support\n");
1348 return -1;
1349 case 0x91d02008:
1350 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001351 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001352 break;
1353 case 0x91d02009:
1354 /* NetBSD/FreeBSD syscall trap. */
1355 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1356 return -1;
1357 case 0x91d02027:
1358 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001359 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001360 break;
1361 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001362# if defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001363 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, sparc_regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001364# else
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001365 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, sparc_regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001366# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001367 return -1;
1368 }
1369
1370 /* Extract the system call number from the registers. */
1371 if (trap == 0x91d02027)
1372 scno = 156;
1373 else
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001374 scno = sparc_regs.u_regs[U_REG_G1];
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001375 if (scno == 0) {
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001376 scno = sparc_regs.u_regs[U_REG_O0];
1377 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 +02001378 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001379#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001380 if (upeek(tcp, PT_GR20, &scno) < 0)
1381 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001382#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001383 /*
1384 * In the new syscall ABI, the system call number is in R3.
1385 */
1386 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1387 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001388
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001389 if (scno < 0) {
1390 /* Odd as it may seem, a glibc bug has been known to cause
1391 glibc to issue bogus negative syscall numbers. So for
1392 our purposes, make strace print what it *should* have been */
1393 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001394 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001395 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001396 "Detected glibc bug: bogus system call"
1397 " number = %ld, correcting to %ld\n",
1398 scno,
1399 correct_scno);
1400 scno = correct_scno;
1401 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001402#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001403 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001404 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001405 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001406#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001407 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1408 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001409#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001410 int currpers;
1411 scno = tile_regs.regs[10];
1412# ifdef __tilepro__
1413 currpers = 1;
1414# else
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001415# ifndef PT_FLAGS_COMPAT
1416# define PT_FLAGS_COMPAT 0x10000 /* from Linux 3.8 on */
1417# endif
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001418 if (tile_regs.flags & PT_FLAGS_COMPAT)
1419 currpers = 1;
1420 else
1421 currpers = 0;
1422# endif
1423 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001424#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001425 if (upeek(tcp, 0, &scno) < 0)
1426 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01001427#elif defined(OR1K)
1428 scno = or1k_regs.gpr[11];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001429#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001430
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001431 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001432 return 1;
1433}
1434
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001435/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001436 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001437 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1438 * 1: ok, continue in trace_syscall_entering().
1439 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001440 * ("????" etc) and bail out.
1441 */
Roland McGratha4d48532005-06-08 20:45:28 +00001442static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001443syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001444{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001445 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001446#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001447 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001448 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001449 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1450 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001451 }
H.J. Lu35be5812012-04-16 13:00:01 +02001452#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001453 {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001454 long rax;
1455 if (x86_io.iov_len == sizeof(i386_regs)) {
1456 /* Sign extend from 32 bits */
1457 rax = (int32_t)i386_regs.eax;
1458 } else {
1459 /* Note: in X32 build, this truncates 64 to 32 bits */
1460 rax = x86_64_regs.rax;
1461 }
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001462 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001463 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001464 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1465 return 0;
1466 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001467 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001468#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001469 /* TODO: we already fetched PT_GPR2 in get_scno
1470 * and stored it in syscall_mode, reuse it here
1471 * instead of re-fetching?
1472 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001473 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001474 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001475 if (syscall_mode != -ENOSYS)
1476 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001477 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001478 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001479 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001480 return 0;
1481 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001482#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001483 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001484 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001485 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001486 if (m68k_d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001487 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001488 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", m68k_d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001489 return 0;
1490 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001491#elif defined(IA64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001492 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001493 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001494 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001495 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001496 if (ia32 && ia64_r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001497 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001498 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", ia64_r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001499 return 0;
1500 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001501#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001502 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001503 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001504 if (cris_r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001505 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001506 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", cris_r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001507 return 0;
1508 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001509#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001510 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001511 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001512 if (microblaze_r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001513 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001514 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", microblaze_r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001515 return 0;
1516 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001517#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001518 return 1;
1519}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001520
Denys Vlasenko146b9442012-03-18 22:10:48 +01001521static void
1522internal_fork(struct tcb *tcp)
1523{
1524#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1525# define ARG_FLAGS 1
1526#else
1527# define ARG_FLAGS 0
1528#endif
1529#ifndef CLONE_UNTRACED
1530# define CLONE_UNTRACED 0x00800000
1531#endif
1532 if ((ptrace_setoptions
1533 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1534 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1535 return;
1536
1537 if (!followfork)
1538 return;
1539
1540 if (entering(tcp)) {
1541 /*
1542 * We won't see the new child if clone is called with
1543 * CLONE_UNTRACED, so we keep the same logic with that option
1544 * and don't trace it.
1545 */
1546 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1547 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1548 return;
1549 setbpt(tcp);
1550 } else {
1551 if (tcp->flags & TCB_BPTSET)
1552 clearbpt(tcp);
1553 }
1554}
1555
1556#if defined(TCB_WAITEXECVE)
1557static void
1558internal_exec(struct tcb *tcp)
1559{
1560 /* Maybe we have post-execve SIGTRAP suppressed? */
1561 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1562 return; /* yes, no need to do anything */
1563
1564 if (exiting(tcp) && syserror(tcp))
1565 /* Error in execve, no post-execve SIGTRAP expected */
1566 tcp->flags &= ~TCB_WAITEXECVE;
1567 else
1568 tcp->flags |= TCB_WAITEXECVE;
1569}
1570#endif
1571
1572static void
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001573syscall_fixup_for_fork_exec(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001574{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001575 /*
1576 * We must always trace a few critical system calls in order to
1577 * correctly support following forks in the presence of tracing
1578 * qualifiers.
1579 */
1580 int (*func)();
1581
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001582 if (!SCNO_IS_VALID(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001583 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001584
1585 func = sysent[tcp->scno].sys_func;
1586
1587 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001588 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001589 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001590 ) {
1591 internal_fork(tcp);
1592 return;
1593 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001594
Denys Vlasenko84703742012-02-25 02:38:52 +01001595#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001596 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001597# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001598 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001599# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001600 ) {
1601 internal_exec(tcp);
1602 return;
1603 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001604#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001605}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001606
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001607/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001608static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001609get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001610{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001611 int i, nargs;
1612
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001613 if (SCNO_IS_VALID(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001614 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001615 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001616 nargs = tcp->u_nargs = MAX_ARGS;
1617
Denys Vlasenko523635f2012-02-25 02:44:25 +01001618#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001619 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001620 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1621 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001622#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001623 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001624 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1625 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001626#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001627 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001628 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001629 long rbs_end;
1630 /* be backwards compatible with kernel < 2.4.4... */
1631# ifndef PT_RBS_END
1632# define PT_RBS_END PT_AR_BSP
1633# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001634
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001635 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1636 return -1;
1637 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001638 return -1;
1639
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001640 sof = (cfm >> 0) & 0x7f;
1641 sol = (cfm >> 7) & 0x7f;
1642 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1643
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001644 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001645 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1646 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1647 return -1;
1648 }
1649 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001650 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1651 PT_R9 /* ECX = out1 */,
1652 PT_R10 /* EDX = out2 */,
1653 PT_R14 /* ESI = out3 */,
1654 PT_R15 /* EDI = out4 */,
1655 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001656
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001657 for (i = 0; i < nargs; ++i) {
1658 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1659 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001660 /* truncate away IVE sign-extension */
1661 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001662 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001663 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001664#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001665 /* N32 and N64 both use up to six registers. */
1666 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001667
1668 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1669 return -1;
1670
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001671 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001672 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001673# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001674 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001675# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001676 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001677#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001678 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001679 long sp;
1680
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001681 if (upeek(tcp, REG_SP, &sp) < 0)
1682 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001683 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001684 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1685 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001686 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001687 (char *)(tcp->u_arg + 4));
1688 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001689 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001690 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001691 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001692 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001693#elif defined(POWERPC)
1694# ifndef PT_ORIG_R3
1695# define PT_ORIG_R3 34
1696# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001697 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001698 if (upeek(tcp, (i==0) ?
1699 (sizeof(unsigned long) * PT_ORIG_R3) :
1700 ((i+PT_R3) * sizeof(unsigned long)),
1701 &tcp->u_arg[i]) < 0)
1702 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001703 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001704#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001705 for (i = 0; i < nargs; ++i)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001706 tcp->u_arg[i] = sparc_regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001707#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001708 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001709 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1710 return -1;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001711#elif defined(ARM) || defined(AARCH64)
1712# if defined(AARCH64)
1713 if (tcp->currpers == 1)
1714 for (i = 0; i < nargs; ++i)
1715 tcp->u_arg[i] = aarch64_regs.regs[i];
1716 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001717# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001718 for (i = 0; i < nargs; ++i)
Denys Vlasenko401374e2013-02-06 18:24:39 +01001719 tcp->u_arg[i] = arm_regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001720#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001721 (void)i;
1722 (void)nargs;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001723 tcp->u_arg[0] = avr32_regs.r12;
1724 tcp->u_arg[1] = avr32_regs.r11;
1725 tcp->u_arg[2] = avr32_regs.r10;
1726 tcp->u_arg[3] = avr32_regs.r9;
1727 tcp->u_arg[4] = avr32_regs.r5;
1728 tcp->u_arg[5] = avr32_regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001729#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001730 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 +02001731
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001732 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001733 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1734 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001735#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001736 static const int syscall_regs[MAX_ARGS] = {
1737 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1738 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001739 };
1740
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001741 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001742 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001743 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001744#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001745 int i;
1746 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001747 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001748
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001749 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001750 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1751 return -1;
Denys Vlasenko6cf36052013-02-15 15:01:38 +01001752#elif defined(I386)
1753 (void)i;
1754 (void)nargs;
1755 tcp->u_arg[0] = i386_regs.ebx;
1756 tcp->u_arg[1] = i386_regs.ecx;
1757 tcp->u_arg[2] = i386_regs.edx;
1758 tcp->u_arg[3] = i386_regs.esi;
1759 tcp->u_arg[4] = i386_regs.edi;
1760 tcp->u_arg[5] = i386_regs.ebp;
H.J. Lu35be5812012-04-16 13:00:01 +02001761#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001762 (void)i;
1763 (void)nargs;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001764 if (x86_io.iov_len != sizeof(i386_regs)) {
1765 /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001766 tcp->u_arg[0] = x86_64_regs.rdi;
1767 tcp->u_arg[1] = x86_64_regs.rsi;
1768 tcp->u_arg[2] = x86_64_regs.rdx;
1769 tcp->u_arg[3] = x86_64_regs.r10;
1770 tcp->u_arg[4] = x86_64_regs.r8;
1771 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001772# ifdef X32
1773 tcp->ext_arg[0] = x86_64_regs.rdi;
1774 tcp->ext_arg[1] = x86_64_regs.rsi;
1775 tcp->ext_arg[2] = x86_64_regs.rdx;
1776 tcp->ext_arg[3] = x86_64_regs.r10;
1777 tcp->ext_arg[4] = x86_64_regs.r8;
1778 tcp->ext_arg[5] = x86_64_regs.r9;
1779# endif
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001780 } else {
1781 /* i386 ABI */
Denys Vlasenko6cf36052013-02-15 15:01:38 +01001782 /* Zero-extend from 32 bits */
1783 /* Use widen_to_long(tcp->u_arg[N]) in syscall handlers
1784 * if you need to use *sign-extended* parameter.
1785 */
1786 tcp->u_arg[0] = (long)(uint32_t)i386_regs.ebx;
1787 tcp->u_arg[1] = (long)(uint32_t)i386_regs.ecx;
1788 tcp->u_arg[2] = (long)(uint32_t)i386_regs.edx;
1789 tcp->u_arg[3] = (long)(uint32_t)i386_regs.esi;
1790 tcp->u_arg[4] = (long)(uint32_t)i386_regs.edi;
1791 tcp->u_arg[5] = (long)(uint32_t)i386_regs.ebp;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001792 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001793#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001794 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001795 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1796 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001797#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001798 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001799 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001800 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001801 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001802
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001803 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001804 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1805 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001806#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001807 for (i = 0; i < nargs; ++i)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001808 tcp->u_arg[i] = tile_regs.regs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001809#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001810 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001811 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1812 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01001813#elif defined(OR1K)
1814 (void)nargs;
1815 for (i = 0; i < 6; ++i)
1816 tcp->u_arg[i] = or1k_regs.gpr[3 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001817#else /* Other architecture (32bits specific) */
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, i*4, &tcp->u_arg[i]) < 0)
1820 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001821#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001822 return 1;
1823}
1824
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001825static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001826trace_syscall_entering(struct tcb *tcp)
1827{
1828 int res, scno_good;
1829
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001830#if defined TCB_WAITEXECVE
1831 if (tcp->flags & TCB_WAITEXECVE) {
1832 /* This is the post-execve SIGTRAP. */
1833 tcp->flags &= ~TCB_WAITEXECVE;
1834 return 0;
1835 }
1836#endif
1837
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001838 scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001839 if (res == 0)
1840 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001841 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001842 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001843 if (res == 0)
1844 return res;
1845 if (res == 1)
1846 res = get_syscall_args(tcp);
1847 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001848
1849 if (res != 1) {
1850 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001851 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001852 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001853 else if (!SCNO_IS_VALID(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001854 tprintf("syscall_%lu(", tcp->scno);
1855 else
1856 tprintf("%s(", sysent[tcp->scno].sys_name);
1857 /*
1858 * " <unavailable>" will be added later by the code which
1859 * detects ptrace errors.
1860 */
1861 goto ret;
1862 }
1863
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001864#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001865 while (SCNO_IS_VALID(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001866# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001867 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001868 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001869 break;
1870 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001871# endif
1872# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001873 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001874 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001875 break;
1876 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001877# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001878 break;
1879 }
1880#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1881
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001882 if (need_fork_exec_workarounds)
1883 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001884
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001885 if ((SCNO_IS_VALID(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001886 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1887 (tracing_paths && !pathtrace_match(tcp))) {
1888 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1889 return 0;
1890 }
1891
1892 tcp->flags &= ~TCB_FILTERED;
1893
1894 if (cflag == CFLAG_ONLY_STATS) {
1895 res = 0;
1896 goto ret;
1897 }
1898
1899 printleader(tcp);
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001900 if (!SCNO_IS_VALID(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001901 tprintf("syscall_%lu(", tcp->scno);
1902 else
1903 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01001904 if (!SCNO_IS_VALID(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001905 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1906 sysent[tcp->scno].sys_func != sys_exit))
1907 res = printargs(tcp);
1908 else
1909 res = (*sysent[tcp->scno].sys_func)(tcp);
1910
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001911 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001912 ret:
1913 tcp->flags |= TCB_INSYSCALL;
1914 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001915 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001916 gettimeofday(&tcp->etime, NULL);
1917 return res;
1918}
1919
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001920/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001921 * 1: ok, continue in trace_syscall_exiting().
1922 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001923 * ("????" etc) and bail out.
1924 */
1925static int
1926get_syscall_result(struct tcb *tcp)
1927{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001928#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001929 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1930 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001931#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001932# define SO_MASK 0x10000000
1933 {
1934 long flags;
1935 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1936 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001937 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001938 return -1;
1939 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001940 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001941 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001942#elif defined(AVR32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001943 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001944#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001945 if (upeek(tcp, PT_R0, &bfin_r0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001946 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001947#elif defined(I386)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001948 /* already done by get_regs */
H.J. Lu35be5812012-04-16 13:00:01 +02001949#elif defined(X86_64) || defined(X32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001950 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001951#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001952# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001953 long psr;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001954 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1955 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001956 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001957 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001958 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001959 return -1;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001960#elif defined(ARM)
1961 /* already done by get_regs */
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001962#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001963 /* register reading already done by get_regs */
1964
1965 /* Used to do this, but we did it on syscall entry already: */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001966 /* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
1967 * else it's personality 0.
1968 */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001969 /*update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));*/
Denys Vlasenko523635f2012-02-25 02:44:25 +01001970#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001971 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001972 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001973#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001974 unsigned long long regs[38];
1975
1976 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1977 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001978 mips_a3 = regs[REG_A3];
1979 mips_r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001980#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001981 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001982 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001983 if (upeek(tcp, REG_V0, &mips_r2) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001984 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001985#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001986 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001987 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001988 if (upeek(tcp, REG_R0, &alpha_r0) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001989 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001990#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001991 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001992#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001993 if (upeek(tcp, PT_GR28, &hppa_r28) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001994 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001995#elif defined(SH)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001996 /* new syscall ABI returns result in R0 */
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001997 if (upeek(tcp, 4*REG_REG0, (long *)&sh_r0) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001998 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001999#elif defined(SH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002000 /* ABI defines result returned in r9 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002001 if (upeek(tcp, REG_GENERAL(9), (long *)&sh64_r9) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002002 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002003#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002004 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002005 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002006#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002007 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002008#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002009 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002010 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01002011#elif defined(OR1K)
2012 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002013#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002014 return 1;
2015}
2016
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002017/* Called at each syscall exit */
2018static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002019syscall_fixup_on_sysexit(struct tcb *tcp)
2020{
Denys Vlasenko523635f2012-02-25 02:44:25 +01002021#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002022 if (syscall_mode != -ENOSYS)
2023 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02002024 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002025 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
2026 /*
2027 * Return from execve.
2028 * Fake a return value of zero. We leave the TCB_WAITEXECVE
2029 * flag set for the post-execve SIGTRAP to see and reset.
2030 */
2031 gpr2 = 0;
2032 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002033#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002034}
2035
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002036/*
2037 * Check the syscall return value register value for whether it is
2038 * a negated errno code indicating an error, or a success return value.
2039 */
2040static inline int
2041is_negated_errno(unsigned long int val)
2042{
2043 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002044#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01002045 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002046 val = (unsigned int) val;
2047 max = (unsigned int) max;
2048 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002049#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002050 return val > max;
2051}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002052
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002053#if defined(X32)
2054static inline int
2055is_negated_errno_x32(unsigned long long val)
2056{
2057 unsigned long long max = -(long long) nerrnos;
2058 /*
2059 * current_wordsize is 4 even in personality 0 (native X32)
2060 * but truncation _must not_ be done in it.
2061 * can't check current_wordsize here!
2062 */
2063 if (current_personality != 0) {
2064 val = (uint32_t) val;
2065 max = (uint32_t) max;
2066 }
2067 return val > max;
2068}
2069#endif
2070
Denys Vlasenko907735a2012-03-21 00:23:16 +01002071/* Returns:
2072 * 1: ok, continue in trace_syscall_exiting().
2073 * -1: error, trace_syscall_exiting() should print error indicator
2074 * ("????" etc) and bail out.
2075 */
Denys Vlasenkoc956ef02013-02-16 14:25:56 +01002076static void
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002077get_error(struct tcb *tcp)
2078{
2079 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002080 int check_errno = 1;
Denys Vlasenkoc956ef02013-02-16 14:25:56 +01002081 if (SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01002082 && (sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS)
2083 ) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002084 check_errno = 0;
2085 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002086#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002087 if (check_errno && is_negated_errno(gpr2)) {
2088 tcp->u_rval = -1;
2089 u_error = -gpr2;
2090 }
2091 else {
2092 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002093 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002094#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002095 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002096 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002097 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002098 }
2099 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002100 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002101 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002102#elif defined(X86_64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002103 long rax;
2104 if (x86_io.iov_len == sizeof(i386_regs)) {
2105 /* Sign extend from 32 bits */
2106 rax = (int32_t)i386_regs.eax;
2107 } else {
2108 rax = x86_64_regs.rax;
2109 }
2110 if (check_errno && is_negated_errno(rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002111 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002112 u_error = -rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002113 }
2114 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002115 tcp->u_rval = rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002116 }
2117#elif defined(X32)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002118 /* In X32, return value is 64-bit (llseek uses one).
2119 * Using merely "long rax" would not work.
2120 */
2121 long long rax;
2122 if (x86_io.iov_len == sizeof(i386_regs)) {
2123 /* Sign extend from 32 bits */
2124 rax = (int32_t)i386_regs.eax;
2125 } else {
2126 rax = x86_64_regs.rax;
2127 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002128 /* Careful: is_negated_errno() works only on longs */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002129 if (check_errno && is_negated_errno_x32(rax)) {
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002130 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002131 u_error = -rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002132 }
2133 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002134 tcp->u_rval = rax; /* truncating */
2135 tcp->u_lrval = rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002136 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002137#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002138 if (ia32) {
2139 int err;
2140
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002141 err = (int)ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002142 if (check_errno && is_negated_errno(err)) {
2143 tcp->u_rval = -1;
2144 u_error = -err;
2145 }
2146 else {
2147 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002148 }
2149 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002150 if (check_errno && ia64_r10) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002151 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002152 u_error = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002153 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002154 tcp->u_rval = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002155 }
2156 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002157#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002158 if (check_errno && mips_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002159 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002160 u_error = mips_r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002161 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002162 tcp->u_rval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002163# if defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002164 tcp->u_lrval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002165# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002166 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002167#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002168 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002169 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002170 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002171 }
2172 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002173 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002174 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002175#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002176 if (check_errno && is_negated_errno(m68k_d0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002177 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002178 u_error = -m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002179 }
2180 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002181 tcp->u_rval = m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002182 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002183#elif defined(ARM) || defined(AARCH64)
2184# if defined(AARCH64)
2185 if (tcp->currpers == 1) {
2186 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2187 tcp->u_rval = -1;
2188 u_error = -aarch64_regs.regs[0];
2189 }
2190 else {
2191 tcp->u_rval = aarch64_regs.regs[0];
2192 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002193 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002194 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01002195# endif
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002196 {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002197 if (check_errno && is_negated_errno(arm_regs.ARM_r0)) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002198 tcp->u_rval = -1;
Denys Vlasenko401374e2013-02-06 18:24:39 +01002199 u_error = -arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002200 }
2201 else {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002202 tcp->u_rval = arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002203 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002204 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002205#elif defined(AVR32)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002206 if (check_errno && avr32_regs.r12 && (unsigned) -avr32_regs.r12 < nerrnos) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002207 tcp->u_rval = -1;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002208 u_error = -avr32_regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002209 }
2210 else {
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002211 tcp->u_rval = avr32_regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002212 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002213#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002214 if (check_errno && is_negated_errno(bfin_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002215 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002216 u_error = -bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002217 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002218 tcp->u_rval = bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002219 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002220#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002221 if (check_errno && alpha_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002222 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002223 u_error = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002224 }
2225 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002226 tcp->u_rval = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002227 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002228#elif defined(SPARC)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002229 if (check_errno && sparc_regs.psr & PSR_C) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002230 tcp->u_rval = -1;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002231 u_error = sparc_regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002232 }
2233 else {
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002234 tcp->u_rval = sparc_regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002235 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002236#elif defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002237 if (check_errno && sparc_regs.tstate & 0x1100000000UL) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002238 tcp->u_rval = -1;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002239 u_error = sparc_regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002240 }
2241 else {
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002242 tcp->u_rval = sparc_regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002243 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002244#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002245 if (check_errno && is_negated_errno(hppa_r28)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002246 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002247 u_error = -hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002248 }
2249 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002250 tcp->u_rval = hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002251 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002252#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002253 if (check_errno && is_negated_errno(sh_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002254 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002255 u_error = -sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002256 }
2257 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002258 tcp->u_rval = sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002259 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002260#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002261 if (check_errno && is_negated_errno(sh64_r9)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002262 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002263 u_error = -sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002264 }
2265 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002266 tcp->u_rval = sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002267 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002268#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002269 if (check_errno && cris_r10 && (unsigned) -cris_r10 < nerrnos) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002270 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002271 u_error = -cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002272 }
2273 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002274 tcp->u_rval = cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002275 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002276#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002277 /*
2278 * The standard tile calling convention returns the value (or negative
2279 * errno) in r0, and zero (or positive errno) in r1.
2280 * Until at least kernel 3.8, however, the r1 value is not reflected
2281 * in ptregs at this point, so we use r0 here.
2282 */
2283 if (check_errno && is_negated_errno(tile_regs.regs[0])) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002284 tcp->u_rval = -1;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002285 u_error = -tile_regs.regs[0];
2286 } else {
2287 tcp->u_rval = tile_regs.regs[0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002288 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002289#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002290 if (check_errno && is_negated_errno(microblaze_r3)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002291 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002292 u_error = -microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002293 }
2294 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002295 tcp->u_rval = microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002296 }
Christian Svensson492f81f2013-02-14 13:26:27 +01002297#elif defined(OR1K)
2298 if (check_errno && is_negated_errno(or1k_regs.gpr[11])) {
2299 tcp->u_rval = -1;
2300 u_error = -or1k_regs.gpr[11];
2301 }
2302 else {
2303 tcp->u_rval = or1k_regs.gpr[11];
2304 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002305#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002306 tcp->u_error = u_error;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002307}
2308
2309static void
2310dumpio(struct tcb *tcp)
2311{
2312 if (syserror(tcp))
2313 return;
2314 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
2315 return;
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01002316 if (!SCNO_IS_VALID(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002317 return;
2318 if (sysent[tcp->scno].sys_func == printargs)
2319 return;
2320 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
2321 if (sysent[tcp->scno].sys_func == sys_read ||
2322 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002323 sysent[tcp->scno].sys_func == sys_recv ||
2324 sysent[tcp->scno].sys_func == sys_recvfrom)
2325 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
2326 else if (sysent[tcp->scno].sys_func == sys_readv)
2327 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2328 return;
2329 }
2330 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
2331 if (sysent[tcp->scno].sys_func == sys_write ||
2332 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002333 sysent[tcp->scno].sys_func == sys_send ||
2334 sysent[tcp->scno].sys_func == sys_sendto)
2335 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
2336 else if (sysent[tcp->scno].sys_func == sys_writev)
2337 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2338 return;
2339 }
2340}
2341
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002342static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002343trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002344{
2345 int sys_res;
2346 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002347 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002348 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002349
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002350 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002351 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002352 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002353
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002354#if SUPPORTED_PERSONALITIES > 1
2355 update_personality(tcp, tcp->currpers);
2356#endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002357 res = (get_regs_error ? -1 : get_syscall_result(tcp));
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002358 if (res == 1) {
2359 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenkoc956ef02013-02-16 14:25:56 +01002360 get_error(tcp); /* never fails */
2361 if (need_fork_exec_workarounds)
2362 syscall_fixup_for_fork_exec(tcp);
2363 if (filtered(tcp))
2364 goto ret;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002365 }
2366
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002367 if (cflag) {
2368 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002369 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002370 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002371 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002372 }
2373 }
2374
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002375 /* If not in -ff mode, and printing_tcp != tcp,
2376 * then the log currently does not end with output
2377 * of _our syscall entry_, but with something else.
2378 * We need to say which syscall's return is this.
2379 *
2380 * Forced reprinting via TCB_REPRINT is used only by
2381 * "strace -ff -oLOG test/threaded_execve" corner case.
2382 * It's the only case when -ff mode needs reprinting.
2383 */
2384 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2385 tcp->flags &= ~TCB_REPRINT;
2386 printleader(tcp);
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01002387 if (!SCNO_IS_VALID(tcp->scno))
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002388 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2389 else
2390 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2391 }
2392 printing_tcp = tcp;
2393
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002394 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002395 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002396 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002397 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002398 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002399 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002400 tcp->flags &= ~TCB_INSYSCALL;
2401 return res;
2402 }
2403
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002404 sys_res = 0;
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01002405 if (!SCNO_IS_VALID(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002406 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002407 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002408 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002409 /* FIXME: not_failing_only (IOW, option -z) is broken:
2410 * failure of syscall is known only after syscall return.
2411 * Thus we end up with something like this on, say, ENOENT:
2412 * open("doesnt_exist", O_RDONLY <unfinished ...>
2413 * {next syscall decode}
2414 * whereas the intended result is that open(...) line
2415 * is not shown at all.
2416 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002417 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002418 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002419 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2420 }
2421
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002422 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002423 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002424 u_error = tcp->u_error;
Denys Vlasenko5721cdb2013-02-16 13:22:38 +01002425 if (!SCNO_IS_VALID(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002426 qual_flags[tcp->scno] & QUAL_RAW) {
2427 if (u_error)
2428 tprintf("= -1 (errno %ld)", u_error);
2429 else
2430 tprintf("= %#lx", tcp->u_rval);
2431 }
2432 else if (!(sys_res & RVAL_NONE) && u_error) {
2433 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002434 /* Blocked signals do not interrupt any syscalls.
2435 * In this case syscalls don't return ERESTARTfoo codes.
2436 *
2437 * Deadly signals set to SIG_DFL interrupt syscalls
2438 * and kill the process regardless of which of the codes below
2439 * is returned by the interrupted syscall.
2440 * In some cases, kernel forces a kernel-generated deadly
2441 * signal to be unblocked and set to SIG_DFL (and thus cause
2442 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2443 * or SIGILL. (The alternative is to leave process spinning
2444 * forever on the faulty instruction - not useful).
2445 *
2446 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2447 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2448 * but kernel will always restart them.
2449 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002450 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002451 /* Most common type of signal-interrupted syscall exit code.
2452 * The system call will be restarted with the same arguments
2453 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2454 */
2455 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002456 break;
2457 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002458 /* Rare. For example, fork() returns this if interrupted.
2459 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2460 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002461 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002462 break;
2463 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002464 /* pause(), rt_sigsuspend() etc use this code.
2465 * SA_RESTART is ignored (assumed not set):
2466 * syscall won't restart (will return EINTR instead)
2467 * even after signal with SA_RESTART set.
2468 * However, after SIG_IGN or SIG_DFL signal it will.
2469 */
2470 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002471 break;
2472 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002473 /* Syscalls like nanosleep(), poll() which can't be
2474 * restarted with their original arguments use this
2475 * code. Kernel will execute restart_syscall() instead,
2476 * which changes arguments before restarting syscall.
2477 * SA_RESTART is ignored (assumed not set) similarly
2478 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2479 * since restart data is saved in "restart block"
2480 * in task struct, and if signal handler uses a syscall
2481 * which in turn saves another such restart block,
2482 * old data is lost and restart becomes impossible)
2483 */
2484 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002485 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002486 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002487 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002488 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002489 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002490 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002491 strerror(u_error));
2492 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002493 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002494 strerror(u_error));
2495 break;
2496 }
2497 if ((sys_res & RVAL_STR) && tcp->auxstr)
2498 tprintf(" (%s)", tcp->auxstr);
2499 }
2500 else {
2501 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002502 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002503 else {
2504 switch (sys_res & RVAL_MASK) {
2505 case RVAL_HEX:
2506 tprintf("= %#lx", tcp->u_rval);
2507 break;
2508 case RVAL_OCTAL:
2509 tprintf("= %#lo", tcp->u_rval);
2510 break;
2511 case RVAL_UDECIMAL:
2512 tprintf("= %lu", tcp->u_rval);
2513 break;
2514 case RVAL_DECIMAL:
2515 tprintf("= %ld", tcp->u_rval);
2516 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002517#if defined(LINUX_MIPSN32) || defined(X32)
2518 /*
2519 case RVAL_LHEX:
2520 tprintf("= %#llx", tcp->u_lrval);
2521 break;
2522 case RVAL_LOCTAL:
2523 tprintf("= %#llo", tcp->u_lrval);
2524 break;
2525 */
2526 case RVAL_LUDECIMAL:
2527 tprintf("= %llu", tcp->u_lrval);
2528 break;
2529 /*
2530 case RVAL_LDECIMAL:
2531 tprintf("= %lld", tcp->u_lrval);
2532 break;
2533 */
2534#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002535 default:
2536 fprintf(stderr,
2537 "invalid rval format\n");
2538 break;
2539 }
2540 }
2541 if ((sys_res & RVAL_STR) && tcp->auxstr)
2542 tprintf(" (%s)", tcp->auxstr);
2543 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002544 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002545 tv_sub(&tv, &tv, &tcp->etime);
2546 tprintf(" <%ld.%06ld>",
2547 (long) tv.tv_sec, (long) tv.tv_usec);
2548 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002549 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002550 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002551 line_ended();
2552
Denys Vlasenko3b738812011-08-22 02:06:35 +02002553 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002554 tcp->flags &= ~TCB_INSYSCALL;
2555 return 0;
2556}
2557
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002558int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002559trace_syscall(struct tcb *tcp)
2560{
2561 return exiting(tcp) ?
2562 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2563}