blob: b92ddc0efbecb672a632a3fc2d83c82b72f103b7 [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
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100121static const struct_sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000122#include "syscallent.h"
123};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000124
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100125#if SUPPORTED_PERSONALITIES > 1
126static 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
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100131#if SUPPORTED_PERSONALITIES > 2
132static 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};
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100162static const struct_ioctlent ioctlent0[] = {
Denys Vlasenko39fca622011-08-20 02:12:33 +0200163#include "ioctlent.h"
164};
165enum { nsyscalls0 = ARRAY_SIZE(sysent0) };
166enum { nerrnos0 = ARRAY_SIZE(errnoent0) };
167enum { nsignals0 = ARRAY_SIZE(signalent0) };
168enum { nioctlents0 = ARRAY_SIZE(ioctlent0) };
Denys Vlasenkoa585c9d2013-02-21 16:15:43 +0100169qualbits_t qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000170
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100171#if SUPPORTED_PERSONALITIES > 1
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};
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100178static 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) };
Denys Vlasenkoa585c9d2013-02-21 16:15:43 +0100185qualbits_t qual_flags1[MAX_QUALS];
Denys Vlasenko39fca622011-08-20 02:12:33 +0200186#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000187
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100188#if SUPPORTED_PERSONALITIES > 2
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};
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100195static 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) };
Denys Vlasenkoa585c9d2013-02-21 16:15:43 +0100202qualbits_t qual_flags2[MAX_QUALS];
Denys Vlasenko39fca622011-08-20 02:12:33 +0200203#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000204
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100205const struct_sysent *sysent = sysent0;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100206const char *const *errnoent = errnoent0;
207const char *const *signalent = signalent0;
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100208const struct_ioctlent *ioctlent = ioctlent0;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100209unsigned nsyscalls = nsyscalls0;
210unsigned nerrnos = nerrnos0;
211unsigned nsignals = nsignals0;
212unsigned nioctlents = nioctlents0;
Denys Vlasenkoa585c9d2013-02-21 16:15:43 +0100213qualbits_t *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 Vlasenkoa9fe13c2013-02-22 13:26:10 +0100257# if SUPPORTED_PERSONALITIES > 2
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
Denys Vlasenkoc1540fe2013-02-21 16:17:08 +0100323static int qual_syscall(), qual_signal(), 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" },
Roland McGrath9797ceb2002-12-30 10:23:00 +0000342 { QUAL_READ, "read", qual_desc, "descriptor" },
343 { QUAL_READ, "reads", qual_desc, "descriptor" },
344 { QUAL_READ, "r", qual_desc, "descriptor" },
345 { QUAL_WRITE, "write", qual_desc, "descriptor" },
346 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
347 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000348 { 0, NULL, NULL, NULL },
349};
350
Roland McGrath9797ceb2002-12-30 10:23:00 +0000351static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000352qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000353{
Roland McGrath138c6a32006-01-12 09:50:49 +0000354 if (pers == 0 || pers < 0) {
355 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000356 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000357 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000358 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000359 }
360
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100361#if SUPPORTED_PERSONALITIES > 1
Roland McGrath138c6a32006-01-12 09:50:49 +0000362 if (pers == 1 || pers < 0) {
363 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000364 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000365 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000366 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000367 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100368#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000369
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100370#if SUPPORTED_PERSONALITIES > 2
Roland McGrath138c6a32006-01-12 09:50:49 +0000371 if (pers == 2 || pers < 0) {
372 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000373 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000374 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000375 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000376 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100377#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000378}
379
380static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000381qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000382{
383 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000384 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000385
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100386 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000387 int i = string_to_uint(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000388 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000389 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000390 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000391 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000392 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000393 for (i = 0; i < nsyscalls0; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000394 if (sysent0[i].sys_name &&
395 strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000396 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000397 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000398 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000399
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100400#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000401 for (i = 0; i < nsyscalls1; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000402 if (sysent1[i].sys_name &&
403 strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000404 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000405 rc = 0;
406 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100407#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000408
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100409#if SUPPORTED_PERSONALITIES > 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000410 for (i = 0; i < nsyscalls2; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000411 if (sysent2[i].sys_name &&
412 strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000413 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000414 rc = 0;
415 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100416#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000417
Roland McGrathfe6b3522005-02-02 04:40:11 +0000418 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000419}
420
421static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000422qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000423{
424 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000425
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100426 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000427 int signo = string_to_uint(s);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000428 if (signo < 0 || signo >= MAX_QUALS)
429 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000430 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000431 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000432 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000433 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000434 s += 3;
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100435 for (i = 0; i <= NSIG; i++) {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000436 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000437 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000438 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000439 }
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100440 }
Roland McGrath76421df2005-02-02 03:51:18 +0000441 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000442}
443
444static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000445qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000446{
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100447 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000448 int desc = string_to_uint(s);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000449 if (desc < 0 || desc >= MAX_QUALS)
450 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000451 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000452 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000453 }
454 return -1;
455}
456
457static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000458lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000459{
460 if (strcmp(s, "file") == 0)
461 return TRACE_FILE;
462 if (strcmp(s, "ipc") == 0)
463 return TRACE_IPC;
464 if (strcmp(s, "network") == 0)
465 return TRACE_NETWORK;
466 if (strcmp(s, "process") == 0)
467 return TRACE_PROCESS;
468 if (strcmp(s, "signal") == 0)
469 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000470 if (strcmp(s, "desc") == 0)
471 return TRACE_DESC;
Namhyung Kim96792962012-10-24 11:41:57 +0900472 if (strcmp(s, "memory") == 0)
473 return TRACE_MEMORY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000474 return -1;
475}
476
477void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000478qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000479{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000480 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000481 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000482 char *copy;
483 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000484 int i, n;
485
486 opt = &qual_options[0];
487 for (i = 0; (p = qual_options[i].option_name); i++) {
488 n = strlen(p);
489 if (strncmp(s, p, n) == 0 && s[n] == '=') {
490 opt = &qual_options[i];
491 s += n + 1;
492 break;
493 }
494 }
495 not = 0;
496 if (*s == '!') {
497 not = 1;
498 s++;
499 }
500 if (strcmp(s, "none") == 0) {
501 not = 1 - not;
502 s = "all";
503 }
504 if (strcmp(s, "all") == 0) {
505 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000506 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000507 }
508 return;
509 }
510 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000511 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000512 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200513 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200514 if (!copy)
515 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000516 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000517 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000518 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000519 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000520 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000521
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100522#if SUPPORTED_PERSONALITIES > 1
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000523 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000524 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000525 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100526#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000527
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100528#if SUPPORTED_PERSONALITIES > 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000529 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000530 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000531 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100532#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000533
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000534 continue;
535 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000536 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100537 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000538 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000539 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000540 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000541 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000542 return;
543}
544
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000545#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000546static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000547decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000548{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000549 unsigned long addr;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +0100550 unsigned int i, n, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000551
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000552 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
553 return;
554
555 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
Denys Vlasenko74ec14f2013-02-21 16:13:47 +0100556 tcp->qual_flg = qual_flags[tcp->scno];
557 tcp->s_ent = &sysent[tcp->scno];
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000558 addr = tcp->u_arg[1];
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100559 size = current_wordsize;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +0100560 n = tcp->s_ent->nargs;
561 for (i = 0; i < n; ++i) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000562 if (size == sizeof(int)) {
563 unsigned int arg;
564 if (umove(tcp, addr, &arg) < 0)
565 arg = 0;
566 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000567 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000568 else {
569 unsigned long arg;
570 if (umove(tcp, addr, &arg) < 0)
571 arg = 0;
572 tcp->u_arg[i] = arg;
573 }
574 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000575 }
576}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000577#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400578
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000579#ifdef SYS_ipc_subcall
580static void
581decode_ipc_subcall(struct tcb *tcp)
582{
Denys Vlasenko74ec14f2013-02-21 16:13:47 +0100583 unsigned int i, n;
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000584
585 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
586 return;
587
588 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
Denys Vlasenko74ec14f2013-02-21 16:13:47 +0100589 tcp->qual_flg = qual_flags[tcp->scno];
590 tcp->s_ent = &sysent[tcp->scno];
591 n = tcp->s_ent->nargs;
592 for (i = 0; i < n; i++)
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000593 tcp->u_arg[i] = tcp->u_arg[i + 1];
594}
595#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000596
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200597int
598printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000599{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200600 if (entering(tcp)) {
601 int i;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +0100602 int n = tcp->s_ent->nargs;
603 for (i = 0; i < n; i++)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200604 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
605 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000606 return 0;
607}
608
Denys Vlasenko72879c62012-02-27 14:18:02 +0100609int
610printargs_lu(struct tcb *tcp)
611{
612 if (entering(tcp)) {
613 int i;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +0100614 int n = tcp->s_ent->nargs;
615 for (i = 0; i < n; i++)
Denys Vlasenko72879c62012-02-27 14:18:02 +0100616 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
617 }
618 return 0;
619}
620
621int
622printargs_ld(struct tcb *tcp)
623{
624 if (entering(tcp)) {
625 int i;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +0100626 int n = tcp->s_ent->nargs;
627 for (i = 0; i < n; i++)
Denys Vlasenko72879c62012-02-27 14:18:02 +0100628 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
629 }
630 return 0;
631}
632
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100633#if defined(SPARC) || defined(SPARC64) || defined(IA64) || defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200634long
635getrval2(struct tcb *tcp)
636{
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100637 long val;
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200638
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100639# if defined(SPARC) || defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100640 val = sparc_regs.u_regs[U_REG_O1];
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100641# elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200642 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
643 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100644# elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200645 if (upeek(tcp, PT_R9, &val) < 0)
646 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100647# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200648
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200649 return val;
650}
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100651#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200652
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200653int
654is_restart_error(struct tcb *tcp)
655{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200656 switch (tcp->u_error) {
657 case ERESTARTSYS:
658 case ERESTARTNOINTR:
659 case ERESTARTNOHAND:
660 case ERESTART_RESTARTBLOCK:
661 return 1;
662 default:
663 break;
664 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200665 return 0;
666}
667
Denys Vlasenko523635f2012-02-25 02:44:25 +0100668#if defined(I386)
Denys Vlasenko2550d482013-02-15 21:04:28 +0100669struct user_regs_struct i386_regs;
H.J. Lu35be5812012-04-16 13:00:01 +0200670#elif defined(X86_64) || defined(X32)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100671/*
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100672 * On i386, pt_regs and user_regs_struct are the same,
673 * but on 64 bit x86, user_regs_struct has six more fields:
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100674 * fs_base, gs_base, ds, es, fs, gs.
675 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
676 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100677struct i386_user_regs_struct {
678 uint32_t ebx;
679 uint32_t ecx;
680 uint32_t edx;
681 uint32_t esi;
682 uint32_t edi;
683 uint32_t ebp;
684 uint32_t eax;
685 uint32_t xds;
686 uint32_t xes;
687 uint32_t xfs;
688 uint32_t xgs;
689 uint32_t orig_eax;
690 uint32_t eip;
691 uint32_t xcs;
692 uint32_t eflags;
693 uint32_t esp;
694 uint32_t xss;
695};
696static union {
697 struct user_regs_struct x86_64_r;
698 struct i386_user_regs_struct i386_r;
699} x86_regs_union;
700# define x86_64_regs x86_regs_union.x86_64_r
701# define i386_regs x86_regs_union.i386_r
702static struct iovec x86_io = {
703 .iov_base = &x86_regs_union
704};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100705#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200706long ia32 = 0; /* not static */
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100707static long ia64_r8, ia64_r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100708#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +0100709static long ppc_result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100710#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100711static long m68k_d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100712#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100713static long bfin_r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100714#elif defined(ARM)
Denys Vlasenko401374e2013-02-06 18:24:39 +0100715struct pt_regs arm_regs; /* not static */
Steve McIntyred8d3bd32012-10-24 17:58:16 +0100716#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100717static union {
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100718 struct user_pt_regs aarch64_r;
719 struct arm_pt_regs arm_r;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100720} arm_regs_union;
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100721# define aarch64_regs arm_regs_union.aarch64_r
722# define arm_regs arm_regs_union.arm_r
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100723static struct iovec aarch64_io = {
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100724 .iov_base = &arm_regs_union
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100725};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100726#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100727static long alpha_r0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100728static long alpha_a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100729#elif defined(AVR32)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100730static struct pt_regs avr32_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100731#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100732struct pt_regs sparc_regs; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100733#elif defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100734static long long mips_a3;
735static long long mips_r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100736#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100737static long mips_a3;
738static long mips_r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100739#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200740static long gpr2;
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200741static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100742#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100743static long hppa_r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100744#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100745static long sh_r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100746#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100747static long sh64_r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100748#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100749static long cris_r10;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100750#elif defined(TILE)
751struct pt_regs tile_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100752#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100753static long microblaze_r3;
Christian Svensson492f81f2013-02-14 13:26:27 +0100754#elif defined(OR1K)
755static struct user_regs_struct or1k_regs;
756static struct iovec or1k_io = {
757 .iov_base = &or1k_regs
758};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100759#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000760
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100761void
762printcall(struct tcb *tcp)
763{
764#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
765 sizeof(long) == 8 ? "[????????????????] " : \
766 NULL /* crash */)
767 if (get_regs_error) {
768 PRINTBADPC;
769 return;
770 }
771#if defined(I386)
772 tprintf("[%08lx] ", i386_regs.eip);
773#elif defined(S390) || defined(S390X)
774 long psw;
775 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
776 PRINTBADPC;
777 return;
778 }
779# ifdef S390
780 tprintf("[%08lx] ", psw);
781# elif S390X
Dmitry V. Levinddba73e2013-02-05 19:01:58 +0000782 tprintf("[%016lx] ", psw);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100783# endif
784#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100785 if (x86_io.iov_len == sizeof(i386_regs)) {
786 tprintf("[%08x] ", (unsigned) i386_regs.eip);
787 } else {
788# if defined(X86_64)
789 tprintf("[%016lx] ", (unsigned long) x86_64_regs.rip);
790# elif defined(X32)
791 /* Note: this truncates 64-bit rip to 32 bits */
792 tprintf("[%08lx] ", (unsigned long) x86_64_regs.rip);
793# endif
794 }
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100795#elif defined(IA64)
796 long ip;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100797 if (upeek(tcp, PT_B0, &ip) < 0) {
798 PRINTBADPC;
799 return;
800 }
801 tprintf("[%08lx] ", ip);
802#elif defined(POWERPC)
803 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100804 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
805 PRINTBADPC;
806 return;
807 }
808# ifdef POWERPC64
809 tprintf("[%016lx] ", pc);
810# else
811 tprintf("[%08lx] ", pc);
812# endif
813#elif defined(M68K)
814 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100815 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
816 tprints("[????????] ");
817 return;
818 }
819 tprintf("[%08lx] ", pc);
820#elif defined(ALPHA)
821 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100822 if (upeek(tcp, REG_PC, &pc) < 0) {
823 tprints("[????????????????] ");
824 return;
825 }
826 tprintf("[%08lx] ", pc);
827#elif defined(SPARC)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100828 tprintf("[%08lx] ", sparc_regs.pc);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100829#elif defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100830 tprintf("[%08lx] ", sparc_regs.tpc);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100831#elif defined(HPPA)
832 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100833 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
834 tprints("[????????] ");
835 return;
836 }
837 tprintf("[%08lx] ", pc);
838#elif defined(MIPS)
839 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100840 if (upeek(tcp, REG_EPC, &pc) < 0) {
841 tprints("[????????] ");
842 return;
843 }
844 tprintf("[%08lx] ", pc);
845#elif defined(SH)
846 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100847 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
848 tprints("[????????] ");
849 return;
850 }
851 tprintf("[%08lx] ", pc);
852#elif defined(SH64)
853 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100854 if (upeek(tcp, REG_PC, &pc) < 0) {
855 tprints("[????????????????] ");
856 return;
857 }
858 tprintf("[%08lx] ", pc);
859#elif defined(ARM)
Denys Vlasenko401374e2013-02-06 18:24:39 +0100860 tprintf("[%08lx] ", arm_regs.ARM_pc);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100861#elif defined(AARCH64)
862 /* tprintf("[%016lx] ", aarch64_regs.regs[???]); */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100863#elif defined(AVR32)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100864 tprintf("[%08lx] ", avr32_regs.pc);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100865#elif defined(BFIN)
866 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100867 if (upeek(tcp, PT_PC, &pc) < 0) {
868 PRINTBADPC;
869 return;
870 }
871 tprintf("[%08lx] ", pc);
872#elif defined(CRISV10)
873 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100874 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
875 PRINTBADPC;
876 return;
877 }
878 tprintf("[%08lx] ", pc);
879#elif defined(CRISV32)
880 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100881 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
882 PRINTBADPC;
883 return;
884 }
885 tprintf("[%08lx] ", pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100886#elif defined(TILE)
887# ifdef _LP64
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500888 tprintf("[%016lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100889# else
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500890 tprintf("[%08lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100891# endif
Christian Svensson492f81f2013-02-14 13:26:27 +0100892#elif defined(OR1K)
893 tprintf("[%08lx] ", or1k_regs.pc);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100894#endif /* architecture */
895}
896
Denys Vlasenko7270de52013-02-21 15:46:34 +0100897/* Shuffle syscall numbers so that we don't have huge gaps in syscall table.
898 * The shuffling should be reversible: shuffle_scno(shuffle_scno(n)) == n.
899 */
900#if defined(ARM) /* So far only ARM needs this */
901static long
902shuffle_scno(unsigned long scno)
903{
904 if (scno <= ARM_LAST_ORDINARY_SYSCALL)
905 return scno;
906
907 /* __ARM_NR_cmpxchg? Swap with LAST_ORDINARY+1 */
908 if (scno == 0x000ffff0)
909 return ARM_LAST_ORDINARY_SYSCALL+1;
910 if (scno == ARM_LAST_ORDINARY_SYSCALL+1)
911 return 0x000ffff0;
912
913 /* Is it ARM specific syscall?
914 * Swap with [LAST_ORDINARY+2, LAST_ORDINARY+2 + LAST_SPECIAL] range.
915 */
916 if (scno >= 0x000f0000
917 && scno <= 0x000f0000 + ARM_LAST_SPECIAL_SYSCALL
918 ) {
919 return scno - 0x000f0000 + (ARM_LAST_ORDINARY_SYSCALL+2);
920 }
921 if (/* scno >= ARM_LAST_ORDINARY_SYSCALL+2 - always true */ 1
922 && scno <= (ARM_LAST_ORDINARY_SYSCALL+2) + ARM_LAST_SPECIAL_SYSCALL
923 ) {
924 return scno + 0x000f0000 - (ARM_LAST_ORDINARY_SYSCALL+2);
925 }
926
927 return scno;
928}
929#else
930# define shuffle_scno(scno) ((long)(scno))
931#endif
932
933static char*
934undefined_scno_name(struct tcb *tcp)
935{
936 static char buf[sizeof("syscall_%lu") + sizeof(long)*3];
937
938 sprintf(buf, "syscall_%lu", shuffle_scno(tcp->scno));
939 return buf;
940}
941
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100942#ifndef get_regs
943long get_regs_error;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100944void
945get_regs(pid_t pid)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100946{
947# if defined(AVR32)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100948 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &avr32_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100949# elif defined(I386)
950 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &i386_regs);
951# elif defined(X86_64) || defined(X32)
Denys Vlasenkoe3b248d2013-02-15 00:24:19 +0100952 /*
953 * PTRACE_GETREGSET was introduced in 2.6.33.
954 * Let's be paranoid and require a bit later kernel.
955 */
956 if (os_release >= KERNEL_VERSION(2,6,35)) {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100957 /*x86_io.iov_base = &x86_regs_union; - already is */
958 x86_io.iov_len = sizeof(x86_regs_union);
959 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (long) &x86_io);
960 } else {
961 /* Use old method, with heuristical detection of 32-bitness */
962 x86_io.iov_len = sizeof(x86_64_regs);
963 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &x86_64_regs);
964 if (!get_regs_error && x86_64_regs.cs == 0x23) {
965 x86_io.iov_len = sizeof(i386_regs);
966 /*
967 * The order is important: i386_regs and x86_64_regs
968 * are overlaid in memory!
969 */
970 i386_regs.ebx = x86_64_regs.rbx;
971 i386_regs.ecx = x86_64_regs.rcx;
972 i386_regs.edx = x86_64_regs.rdx;
973 i386_regs.esi = x86_64_regs.rsi;
974 i386_regs.edi = x86_64_regs.rdi;
975 i386_regs.ebp = x86_64_regs.rbp;
976 i386_regs.eax = x86_64_regs.rax;
977 /*i386_regs.xds = x86_64_regs.ds; unused by strace */
978 /*i386_regs.xes = x86_64_regs.es; ditto... */
979 /*i386_regs.xfs = x86_64_regs.fs;*/
980 /*i386_regs.xgs = x86_64_regs.gs;*/
981 i386_regs.orig_eax = x86_64_regs.orig_rax;
982 i386_regs.eip = x86_64_regs.rip;
983 /*i386_regs.xcs = x86_64_regs.cs;*/
984 /*i386_regs.eflags = x86_64_regs.eflags;*/
985 i386_regs.esp = x86_64_regs.rsp;
986 /*i386_regs.xss = x86_64_regs.ss;*/
987 }
988 }
Denys Vlasenko401374e2013-02-06 18:24:39 +0100989# elif defined(ARM)
990 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (void *)&arm_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100991# elif defined(AARCH64)
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100992 /*aarch64_io.iov_base = &arm_regs_union; - already is */
993 aarch64_io.iov_len = sizeof(arm_regs_union);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100994 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void *)&aarch64_io);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100995# if 0
996 /* Paranoia checks */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100997 if (get_regs_error)
998 return;
999 switch (aarch64_io.iov_len) {
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001000 case sizeof(aarch64_regs):
1001 /* We are in 64-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001002 break;
1003 case sizeof(arm_regs):
1004 /* We are in 32-bit mode */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001005 break;
1006 default:
1007 get_regs_error = -1;
1008 break;
1009 }
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001010# endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001011# elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001012 get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&sparc_regs, 0);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001013# elif defined(TILE)
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -05001014 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &tile_regs);
Christian Svensson492f81f2013-02-14 13:26:27 +01001015# elif defined(OR1K)
1016 or1k_io.iov_len = sizeof(or1k_regs);
1017 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &or1k_io);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001018# endif
1019}
1020#endif
1021
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001022/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001023 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1024 * 1: ok, continue in trace_syscall_entering().
1025 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001026 * ("????" etc) and bail out.
1027 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001028static int
Denys Vlasenko06602d92011-08-24 17:53:52 +02001029get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001030{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001031 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001032
Denys Vlasenko523635f2012-02-25 02:44:25 +01001033#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001034 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001035 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +00001036
1037 if (syscall_mode != -ENOSYS) {
1038 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001039 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +00001040 */
1041 scno = syscall_mode;
1042 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001043 /*
Michal Ludvig882eda82002-11-11 12:50:47 +00001044 * Old style of "passing" the scno via the SVC instruction.
1045 */
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001046 long psw;
Michal Ludvig882eda82002-11-11 12:50:47 +00001047 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001048 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +02001049 static const int gpr_offset[16] = {
1050 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
1051 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
1052 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
1053 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
1054 };
Roland McGrath761b5d72002-12-15 23:58:31 +00001055
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001056 if (upeek(tcp, PT_PSWADDR, &psw) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +00001057 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +00001058 errno = 0;
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001059 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(psw - sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +00001060 if (errno) {
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001061 perror_msg("%s", "peektext(psw-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +00001062 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +00001063 }
Michal Ludvig882eda82002-11-11 12:50:47 +00001064
1065 /*
1066 * We have to check if the SVC got executed directly or via an
1067 * EXECUTE instruction. In case of EXECUTE it is necessary to do
1068 * instruction decoding to derive the system call number.
1069 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
1070 * so that this doesn't work if a SVC opcode is part of an EXECUTE
1071 * opcode. Since there is no way to find out the opcode size this
1072 * is the best we can do...
1073 */
Michal Ludvig882eda82002-11-11 12:50:47 +00001074 if ((opcode & 0xff00) == 0x0a00) {
1075 /* SVC opcode */
1076 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +00001077 }
Michal Ludvig882eda82002-11-11 12:50:47 +00001078 else {
1079 /* SVC got executed by EXECUTE instruction */
1080
1081 /*
1082 * Do instruction decoding of EXECUTE. If you really want to
1083 * understand this, read the Principles of Operations.
1084 */
1085 svc_addr = (void *) (opcode & 0xfff);
1086
1087 tmp = 0;
1088 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001089 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001090 return -1;
1091 svc_addr += tmp;
1092
1093 tmp = 0;
1094 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001095 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001096 return -1;
1097 svc_addr += tmp;
1098
Denys Vlasenkofb036672009-01-23 16:30:26 +00001099 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +00001100 if (errno)
1101 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001102# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +00001103 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001104# else
Michal Ludvig882eda82002-11-11 12:50:47 +00001105 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001106# endif
Michal Ludvig882eda82002-11-11 12:50:47 +00001107 tmp = 0;
1108 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001109 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001110 return -1;
1111
1112 scno = (scno | tmp) & 0xff;
1113 }
1114 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001115#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001116 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001117 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001118# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001119 /* TODO: speed up strace by not doing this at every syscall.
1120 * We only need to do it after execve.
1121 */
1122 int currpers;
1123 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +02001124
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001125 /* Check for 64/32 bit mode. */
1126 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
1127 return -1;
1128 /* SF is bit 0 of MSR */
1129 if (val < 0)
1130 currpers = 0;
1131 else
1132 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001133 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001134# endif
1135#elif defined(AVR32)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001136 scno = avr32_regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001137#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001138 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001139 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001140#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001141 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +02001142#elif defined(X86_64) || defined(X32)
1143# ifndef __X32_SYSCALL_BIT
1144# define __X32_SYSCALL_BIT 0x40000000
1145# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001146 int currpers;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001147# if 1
1148 /* GETREGSET of NT_PRSTATUS tells us regset size,
1149 * which unambiguously detects i386.
1150 *
1151 * Linux kernel distinguishes x86-64 and x32 processes
1152 * solely by looking at __X32_SYSCALL_BIT:
1153 * arch/x86/include/asm/compat.h::is_x32_task():
1154 * if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)
1155 * return true;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001156 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001157 if (x86_io.iov_len == sizeof(i386_regs)) {
1158 scno = i386_regs.orig_eax;
1159 currpers = 1;
1160 } else {
1161 scno = x86_64_regs.orig_rax;
1162 currpers = 0;
1163 if (scno & __X32_SYSCALL_BIT) {
1164 scno -= __X32_SYSCALL_BIT;
1165 currpers = 2;
1166 }
1167 }
1168# elif 0
1169 /* cs = 0x33 for long mode (native 64 bit and x32)
1170 * cs = 0x23 for compatibility mode (32 bit)
1171 * ds = 0x2b for x32 mode (x86-64 in 32 bit)
1172 */
1173 scno = x86_64_regs.orig_rax;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001174 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001175 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +02001176 case 0x33:
1177 if (x86_64_regs.ds == 0x2b) {
1178 currpers = 2;
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001179 scno &= ~__X32_SYSCALL_BIT;
H.J. Lu35be5812012-04-16 13:00:01 +02001180 } else
1181 currpers = 0;
1182 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001183 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001184 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001185 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001186 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001187 currpers = current_personality;
1188 break;
1189 }
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001190# elif 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001191 /* This version analyzes the opcode of a syscall instruction.
1192 * (int 0x80 on i386 vs. syscall on x86-64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001193 * It works, but is too complicated, and strictly speaking, unreliable.
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001194 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001195 unsigned long call, rip = x86_64_regs.rip;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001196 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
1197 rip -= 2;
1198 errno = 0;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001199 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001200 if (errno)
1201 fprintf(stderr, "ptrace_peektext failed: %s\n",
1202 strerror(errno));
1203 switch (call & 0xffff) {
1204 /* x86-64: syscall = 0x0f 0x05 */
1205 case 0x050f: currpers = 0; break;
1206 /* i386: int 0x80 = 0xcd 0x80 */
1207 case 0x80cd: currpers = 1; break;
1208 default:
1209 currpers = current_personality;
1210 fprintf(stderr,
1211 "Unknown syscall opcode (0x%04X) while "
1212 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001213 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001214 break;
1215 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001216# endif
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001217
H.J. Lu35be5812012-04-16 13:00:01 +02001218# ifdef X32
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001219 /* If we are built for a x32 system, then personality 0 is x32
1220 * (not x86_64), and stracing of x86_64 apps is not supported.
1221 * Stracing of i386 apps is still supported.
H.J. Lu085e4282012-04-17 11:05:04 -07001222 */
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001223 if (currpers == 0) {
1224 fprintf(stderr, "syscall_%lu(...) in unsupported "
1225 "64-bit mode of process PID=%d\n",
1226 scno, tcp->pid);
1227 return 0;
H.J. Lu35be5812012-04-16 13:00:01 +02001228 }
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001229 currpers &= ~2; /* map 2,1 to 0,1 */
H.J. Lu35be5812012-04-16 13:00:01 +02001230# endif
H.J. Lu085e4282012-04-17 11:05:04 -07001231 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001232#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001233# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001234 long psr;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001235 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001236 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001237 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001238 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001239 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001240 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001241 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001242 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001243 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001244#elif defined(AARCH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001245 switch (aarch64_io.iov_len) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001246 case sizeof(aarch64_regs):
1247 /* We are in 64-bit mode */
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001248 scno = aarch64_regs.regs[8];
1249 update_personality(tcp, 1);
1250 break;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001251 case sizeof(arm_regs):
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001252 /* We are in 32-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001253 scno = arm_regs.ARM_r7;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001254 update_personality(tcp, 0);
1255 break;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001256 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001257#elif defined(ARM)
Denys Vlasenkoe7030e52013-02-20 18:08:25 +01001258 if (arm_regs.ARM_ip != 0) {
1259 /* It is not a syscall entry */
1260 fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001261 tcp->flags |= TCB_INSYSCALL;
Denys Vlasenkoe7030e52013-02-20 18:08:25 +01001262 return 0;
1263 }
1264 /* Note: we support only 32-bit CPUs, not 26-bit */
1265
1266 if (arm_regs.ARM_cpsr & 0x20) {
1267 /* Thumb mode */
1268 scno = arm_regs.ARM_r7;
1269 } else {
1270 /* ARM mode */
1271 errno = 0;
1272 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(arm_regs.ARM_pc - 4), NULL);
1273 if (errno)
1274 return -1;
1275
1276 /* EABI syscall convention? */
1277 if (scno == 0xef000000) {
1278 scno = arm_regs.ARM_r7; /* yes */
1279 } else {
1280 if ((scno & 0x0ff00000) != 0x0f900000) {
1281 fprintf(stderr, "pid %d unknown syscall trap 0x%08lx\n",
1282 tcp->pid, scno);
1283 return -1;
1284 }
1285 /* Fixup the syscall number */
1286 scno &= 0x000fffff;
1287 }
1288 }
Denys Vlasenko7270de52013-02-21 15:46:34 +01001289
1290 scno = shuffle_scno(scno);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001291#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001292 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001293 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001294#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001295 unsigned long long regs[38];
1296
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001297 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001298 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001299 mips_a3 = regs[REG_A3];
1300 mips_r2 = regs[REG_V0];
Roland McGrath542c2c62008-05-20 01:11:56 +00001301
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001302 scno = mips_r2;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001303 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001304 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001305 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001306 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001307 return 0;
1308 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001309 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001310#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001311 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001312 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001313 if (upeek(tcp, REG_V0, &scno) < 0)
1314 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001315
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001316 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001317 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001318 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001319 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001320 return 0;
1321 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001322 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001323#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001324 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001325 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001326 if (upeek(tcp, REG_R0, &scno) < 0)
1327 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001328
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001329 /*
1330 * Do some sanity checks to figure out if it's
1331 * really a syscall entry
1332 */
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001333 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001334 if (alpha_a3 == 0 || alpha_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001335 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001336 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001337 return 0;
1338 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001339 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001340#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001341 /* Disassemble the syscall trap. */
1342 /* Retrieve the syscall trap instruction. */
Denys Vlasenko46455822013-02-05 17:02:59 +01001343 unsigned long trap;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001344 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001345# if defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001346 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)sparc_regs.tpc, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001347 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001348# else
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001349 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)sparc_regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001350# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001351 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001352 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001353
1354 /* Disassemble the trap to see what personality to use. */
1355 switch (trap) {
1356 case 0x91d02010:
1357 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001358 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001359 break;
1360 case 0x91d0206d:
1361 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001362 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001363 break;
1364 case 0x91d02000:
1365 /* SunOS syscall trap. (pers 1) */
1366 fprintf(stderr, "syscall: SunOS no support\n");
1367 return -1;
1368 case 0x91d02008:
1369 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001370 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001371 break;
1372 case 0x91d02009:
1373 /* NetBSD/FreeBSD syscall trap. */
1374 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1375 return -1;
1376 case 0x91d02027:
1377 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001378 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001379 break;
1380 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001381# if defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001382 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, sparc_regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001383# else
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001384 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, sparc_regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001385# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001386 return -1;
1387 }
1388
1389 /* Extract the system call number from the registers. */
1390 if (trap == 0x91d02027)
1391 scno = 156;
1392 else
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001393 scno = sparc_regs.u_regs[U_REG_G1];
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001394 if (scno == 0) {
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001395 scno = sparc_regs.u_regs[U_REG_O0];
1396 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 +02001397 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001398#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001399 if (upeek(tcp, PT_GR20, &scno) < 0)
1400 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001401#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001402 /*
1403 * In the new syscall ABI, the system call number is in R3.
1404 */
1405 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1406 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001407
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001408 if (scno < 0) {
1409 /* Odd as it may seem, a glibc bug has been known to cause
1410 glibc to issue bogus negative syscall numbers. So for
1411 our purposes, make strace print what it *should* have been */
1412 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001413 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001414 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001415 "Detected glibc bug: bogus system call"
1416 " number = %ld, correcting to %ld\n",
1417 scno,
1418 correct_scno);
1419 scno = correct_scno;
1420 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001421#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001422 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001423 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001424 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001425#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001426 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1427 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001428#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001429 int currpers;
1430 scno = tile_regs.regs[10];
1431# ifdef __tilepro__
1432 currpers = 1;
1433# else
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001434# ifndef PT_FLAGS_COMPAT
1435# define PT_FLAGS_COMPAT 0x10000 /* from Linux 3.8 on */
1436# endif
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001437 if (tile_regs.flags & PT_FLAGS_COMPAT)
1438 currpers = 1;
1439 else
1440 currpers = 0;
1441# endif
1442 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001443#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001444 if (upeek(tcp, 0, &scno) < 0)
1445 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01001446#elif defined(OR1K)
1447 scno = or1k_regs.gpr[11];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001448#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001449
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001450 tcp->scno = scno;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001451 if (SCNO_IS_VALID(tcp->scno)) {
1452 tcp->s_ent = &sysent[scno];
1453 tcp->qual_flg = qual_flags[scno];
1454 } else {
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +01001455 static const struct_sysent unknown = {
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001456 .nargs = MAX_ARGS,
1457 .sys_flags = 0,
1458 .sys_func = printargs,
1459 .sys_name = "unknown", /* not used */
1460 };
1461 tcp->s_ent = &unknown;
1462 tcp->qual_flg = UNDEFINED_SCNO | QUAL_RAW | DEFAULT_QUAL_FLAGS;
1463 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00001464 return 1;
1465}
1466
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001467/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001468 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001469 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1470 * 1: ok, continue in trace_syscall_entering().
1471 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001472 * ("????" etc) and bail out.
1473 */
Roland McGratha4d48532005-06-08 20:45:28 +00001474static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001475syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001476{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001477 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001478#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001479 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001480 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001481 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1482 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001483 }
H.J. Lu35be5812012-04-16 13:00:01 +02001484#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001485 {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001486 long rax;
1487 if (x86_io.iov_len == sizeof(i386_regs)) {
1488 /* Sign extend from 32 bits */
1489 rax = (int32_t)i386_regs.eax;
1490 } else {
1491 /* Note: in X32 build, this truncates 64 to 32 bits */
1492 rax = x86_64_regs.rax;
1493 }
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001494 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001495 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001496 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1497 return 0;
1498 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001499 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001500#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001501 /* TODO: we already fetched PT_GPR2 in get_scno
1502 * and stored it in syscall_mode, reuse it here
1503 * instead of re-fetching?
1504 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001505 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001506 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001507 if (syscall_mode != -ENOSYS)
1508 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001509 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001510 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001511 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001512 return 0;
1513 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001514#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001515 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001516 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001517 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001518 if (m68k_d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001519 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001520 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", m68k_d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001521 return 0;
1522 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001523#elif defined(IA64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001524 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001525 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001526 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001527 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001528 if (ia32 && ia64_r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001529 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001530 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", ia64_r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001531 return 0;
1532 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001533#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001534 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001535 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001536 if (cris_r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001537 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001538 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", cris_r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001539 return 0;
1540 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001541#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001542 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001543 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001544 if (microblaze_r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001545 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001546 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", microblaze_r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001547 return 0;
1548 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001549#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001550 return 1;
1551}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001552
Denys Vlasenko146b9442012-03-18 22:10:48 +01001553static void
1554internal_fork(struct tcb *tcp)
1555{
1556#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1557# define ARG_FLAGS 1
1558#else
1559# define ARG_FLAGS 0
1560#endif
1561#ifndef CLONE_UNTRACED
1562# define CLONE_UNTRACED 0x00800000
1563#endif
1564 if ((ptrace_setoptions
1565 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1566 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1567 return;
1568
1569 if (!followfork)
1570 return;
1571
1572 if (entering(tcp)) {
1573 /*
1574 * We won't see the new child if clone is called with
1575 * CLONE_UNTRACED, so we keep the same logic with that option
1576 * and don't trace it.
1577 */
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001578 if ((tcp->s_ent->sys_func == sys_clone)
1579 && (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED)
1580 )
Denys Vlasenko146b9442012-03-18 22:10:48 +01001581 return;
1582 setbpt(tcp);
1583 } else {
1584 if (tcp->flags & TCB_BPTSET)
1585 clearbpt(tcp);
1586 }
1587}
1588
1589#if defined(TCB_WAITEXECVE)
1590static void
1591internal_exec(struct tcb *tcp)
1592{
1593 /* Maybe we have post-execve SIGTRAP suppressed? */
1594 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1595 return; /* yes, no need to do anything */
1596
1597 if (exiting(tcp) && syserror(tcp))
1598 /* Error in execve, no post-execve SIGTRAP expected */
1599 tcp->flags &= ~TCB_WAITEXECVE;
1600 else
1601 tcp->flags |= TCB_WAITEXECVE;
1602}
1603#endif
1604
1605static void
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001606syscall_fixup_for_fork_exec(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001607{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001608 /*
1609 * We must always trace a few critical system calls in order to
1610 * correctly support following forks in the presence of tracing
1611 * qualifiers.
1612 */
1613 int (*func)();
1614
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001615 func = tcp->s_ent->sys_func;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001616
1617 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001618 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001619 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001620 ) {
1621 internal_fork(tcp);
1622 return;
1623 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001624
Denys Vlasenko84703742012-02-25 02:38:52 +01001625#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001626 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001627# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001628 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001629# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001630 ) {
1631 internal_exec(tcp);
1632 return;
1633 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001634#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001635}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001636
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001637/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001638static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001639get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001640{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001641 int i, nargs;
1642
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001643 nargs = tcp->s_ent->nargs;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001644
Denys Vlasenko523635f2012-02-25 02:44:25 +01001645#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001646 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001647 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1648 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001649#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001650 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001651 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1652 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001653#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001654 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001655 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001656 long rbs_end;
1657 /* be backwards compatible with kernel < 2.4.4... */
1658# ifndef PT_RBS_END
1659# define PT_RBS_END PT_AR_BSP
1660# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001661
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001662 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1663 return -1;
1664 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001665 return -1;
1666
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001667 sof = (cfm >> 0) & 0x7f;
1668 sol = (cfm >> 7) & 0x7f;
1669 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1670
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001671 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001672 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1673 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1674 return -1;
1675 }
1676 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001677 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1678 PT_R9 /* ECX = out1 */,
1679 PT_R10 /* EDX = out2 */,
1680 PT_R14 /* ESI = out3 */,
1681 PT_R15 /* EDI = out4 */,
1682 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001683
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001684 for (i = 0; i < nargs; ++i) {
1685 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1686 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001687 /* truncate away IVE sign-extension */
1688 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001689 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001690 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001691#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001692 /* N32 and N64 both use up to six registers. */
1693 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001694
1695 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1696 return -1;
1697
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001698 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001699 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001700# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001701 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001702# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001703 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001704#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001705 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001706 long sp;
1707
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001708 if (upeek(tcp, REG_SP, &sp) < 0)
1709 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001710 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001711 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1712 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001713 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001714 (char *)(tcp->u_arg + 4));
1715 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001716 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001717 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001718 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001719 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001720#elif defined(POWERPC)
1721# ifndef PT_ORIG_R3
1722# define PT_ORIG_R3 34
1723# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001724 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001725 if (upeek(tcp, (i==0) ?
1726 (sizeof(unsigned long) * PT_ORIG_R3) :
1727 ((i+PT_R3) * sizeof(unsigned long)),
1728 &tcp->u_arg[i]) < 0)
1729 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001730 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001731#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001732 for (i = 0; i < nargs; ++i)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001733 tcp->u_arg[i] = sparc_regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001734#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001735 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001736 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1737 return -1;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001738#elif defined(ARM) || defined(AARCH64)
1739# if defined(AARCH64)
1740 if (tcp->currpers == 1)
1741 for (i = 0; i < nargs; ++i)
1742 tcp->u_arg[i] = aarch64_regs.regs[i];
1743 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001744# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001745 for (i = 0; i < nargs; ++i)
Denys Vlasenko401374e2013-02-06 18:24:39 +01001746 tcp->u_arg[i] = arm_regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001747#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001748 (void)i;
1749 (void)nargs;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001750 tcp->u_arg[0] = avr32_regs.r12;
1751 tcp->u_arg[1] = avr32_regs.r11;
1752 tcp->u_arg[2] = avr32_regs.r10;
1753 tcp->u_arg[3] = avr32_regs.r9;
1754 tcp->u_arg[4] = avr32_regs.r5;
1755 tcp->u_arg[5] = avr32_regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001756#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001757 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 +02001758
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001759 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001760 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1761 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001762#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001763 static const int syscall_regs[MAX_ARGS] = {
1764 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1765 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001766 };
1767
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001768 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001769 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001770 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001771#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001772 int i;
1773 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001774 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001775
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001776 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001777 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1778 return -1;
Denys Vlasenko6cf36052013-02-15 15:01:38 +01001779#elif defined(I386)
1780 (void)i;
1781 (void)nargs;
1782 tcp->u_arg[0] = i386_regs.ebx;
1783 tcp->u_arg[1] = i386_regs.ecx;
1784 tcp->u_arg[2] = i386_regs.edx;
1785 tcp->u_arg[3] = i386_regs.esi;
1786 tcp->u_arg[4] = i386_regs.edi;
1787 tcp->u_arg[5] = i386_regs.ebp;
H.J. Lu35be5812012-04-16 13:00:01 +02001788#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001789 (void)i;
1790 (void)nargs;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001791 if (x86_io.iov_len != sizeof(i386_regs)) {
1792 /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001793 tcp->u_arg[0] = x86_64_regs.rdi;
1794 tcp->u_arg[1] = x86_64_regs.rsi;
1795 tcp->u_arg[2] = x86_64_regs.rdx;
1796 tcp->u_arg[3] = x86_64_regs.r10;
1797 tcp->u_arg[4] = x86_64_regs.r8;
1798 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001799# ifdef X32
1800 tcp->ext_arg[0] = x86_64_regs.rdi;
1801 tcp->ext_arg[1] = x86_64_regs.rsi;
1802 tcp->ext_arg[2] = x86_64_regs.rdx;
1803 tcp->ext_arg[3] = x86_64_regs.r10;
1804 tcp->ext_arg[4] = x86_64_regs.r8;
1805 tcp->ext_arg[5] = x86_64_regs.r9;
1806# endif
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001807 } else {
1808 /* i386 ABI */
Denys Vlasenko6cf36052013-02-15 15:01:38 +01001809 /* Zero-extend from 32 bits */
1810 /* Use widen_to_long(tcp->u_arg[N]) in syscall handlers
1811 * if you need to use *sign-extended* parameter.
1812 */
1813 tcp->u_arg[0] = (long)(uint32_t)i386_regs.ebx;
1814 tcp->u_arg[1] = (long)(uint32_t)i386_regs.ecx;
1815 tcp->u_arg[2] = (long)(uint32_t)i386_regs.edx;
1816 tcp->u_arg[3] = (long)(uint32_t)i386_regs.esi;
1817 tcp->u_arg[4] = (long)(uint32_t)i386_regs.edi;
1818 tcp->u_arg[5] = (long)(uint32_t)i386_regs.ebp;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001819 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001820#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001821 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001822 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1823 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001824#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001825 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001826 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001827 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001828 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001829
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001830 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001831 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1832 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001833#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001834 for (i = 0; i < nargs; ++i)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001835 tcp->u_arg[i] = tile_regs.regs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001836#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001837 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001838 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1839 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01001840#elif defined(OR1K)
1841 (void)nargs;
1842 for (i = 0; i < 6; ++i)
1843 tcp->u_arg[i] = or1k_regs.gpr[3 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001844#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001845 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001846 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1847 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001848#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001849 return 1;
1850}
1851
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001852static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001853trace_syscall_entering(struct tcb *tcp)
1854{
1855 int res, scno_good;
1856
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001857#if defined TCB_WAITEXECVE
1858 if (tcp->flags & TCB_WAITEXECVE) {
1859 /* This is the post-execve SIGTRAP. */
1860 tcp->flags &= ~TCB_WAITEXECVE;
1861 return 0;
1862 }
1863#endif
1864
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001865 scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001866 if (res == 0)
1867 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001868 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001869 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001870 if (res == 0)
1871 return res;
1872 if (res == 1)
1873 res = get_syscall_args(tcp);
1874 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001875
1876 if (res != 1) {
1877 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001878 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001879 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001880 else if (tcp->qual_flg & UNDEFINED_SCNO)
Denys Vlasenko7270de52013-02-21 15:46:34 +01001881 tprintf("%s(", undefined_scno_name(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001882 else
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001883 tprintf("%s(", tcp->s_ent->sys_name);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001884 /*
1885 * " <unavailable>" will be added later by the code which
1886 * detects ptrace errors.
1887 */
1888 goto ret;
1889 }
1890
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001891#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001892 while (1) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001893# ifdef SYS_socket_subcall
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001894 if (tcp->s_ent->sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001895 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001896 break;
1897 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001898# endif
1899# ifdef SYS_ipc_subcall
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001900 if (tcp->s_ent->sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001901 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001902 break;
1903 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001904# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001905 break;
1906 }
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001907#endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001908
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001909 if (need_fork_exec_workarounds)
1910 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001911
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001912 if (!(tcp->qual_flg & QUAL_TRACE)
1913 || (tracing_paths && !pathtrace_match(tcp))
1914 ) {
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001915 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1916 return 0;
1917 }
1918
1919 tcp->flags &= ~TCB_FILTERED;
1920
1921 if (cflag == CFLAG_ONLY_STATS) {
1922 res = 0;
1923 goto ret;
1924 }
1925
1926 printleader(tcp);
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001927 if (tcp->qual_flg & UNDEFINED_SCNO)
Denys Vlasenko7270de52013-02-21 15:46:34 +01001928 tprintf("%s(", undefined_scno_name(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001929 else
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001930 tprintf("%s(", tcp->s_ent->sys_name);
1931 if ((tcp->qual_flg & QUAL_RAW) && tcp->s_ent->sys_func != sys_exit)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001932 res = printargs(tcp);
1933 else
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001934 res = tcp->s_ent->sys_func(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001935
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001936 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001937 ret:
1938 tcp->flags |= TCB_INSYSCALL;
1939 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001940 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001941 gettimeofday(&tcp->etime, NULL);
1942 return res;
1943}
1944
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001945/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001946 * 1: ok, continue in trace_syscall_exiting().
1947 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001948 * ("????" etc) and bail out.
1949 */
1950static int
1951get_syscall_result(struct tcb *tcp)
1952{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001953#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001954 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1955 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001956#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001957# define SO_MASK 0x10000000
1958 {
1959 long flags;
1960 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1961 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001962 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001963 return -1;
1964 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001965 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001966 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001967#elif defined(AVR32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001968 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001969#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001970 if (upeek(tcp, PT_R0, &bfin_r0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001971 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001972#elif defined(I386)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001973 /* already done by get_regs */
H.J. Lu35be5812012-04-16 13:00:01 +02001974#elif defined(X86_64) || defined(X32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001975 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001976#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001977# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001978 long psr;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001979 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1980 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001981 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001982 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001983 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001984 return -1;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001985#elif defined(ARM)
1986 /* already done by get_regs */
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001987#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001988 /* register reading already done by get_regs */
1989
1990 /* Used to do this, but we did it on syscall entry already: */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001991 /* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
1992 * else it's personality 0.
1993 */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001994 /*update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));*/
Denys Vlasenko523635f2012-02-25 02:44:25 +01001995#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001996 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001997 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001998#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001999 unsigned long long regs[38];
2000
2001 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
2002 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002003 mips_a3 = regs[REG_A3];
2004 mips_r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01002005#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002006 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002007 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002008 if (upeek(tcp, REG_V0, &mips_r2) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002009 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002010#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002011 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002012 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002013 if (upeek(tcp, REG_R0, &alpha_r0) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002014 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002015#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002016 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002017#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002018 if (upeek(tcp, PT_GR28, &hppa_r28) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002019 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002020#elif defined(SH)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002021 /* new syscall ABI returns result in R0 */
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002022 if (upeek(tcp, 4*REG_REG0, (long *)&sh_r0) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002023 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002024#elif defined(SH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002025 /* ABI defines result returned in r9 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002026 if (upeek(tcp, REG_GENERAL(9), (long *)&sh64_r9) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002027 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002028#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002029 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002030 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002031#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002032 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002033#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002034 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002035 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01002036#elif defined(OR1K)
2037 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002038#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002039 return 1;
2040}
2041
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002042/* Called at each syscall exit */
2043static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002044syscall_fixup_on_sysexit(struct tcb *tcp)
2045{
Denys Vlasenko523635f2012-02-25 02:44:25 +01002046#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002047 if (syscall_mode != -ENOSYS)
2048 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02002049 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002050 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
2051 /*
2052 * Return from execve.
2053 * Fake a return value of zero. We leave the TCB_WAITEXECVE
2054 * flag set for the post-execve SIGTRAP to see and reset.
2055 */
2056 gpr2 = 0;
2057 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002058#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002059}
2060
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002061/*
2062 * Check the syscall return value register value for whether it is
2063 * a negated errno code indicating an error, or a success return value.
2064 */
2065static inline int
2066is_negated_errno(unsigned long int val)
2067{
2068 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko2544f982013-02-19 17:39:56 +01002069#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01002070 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002071 val = (unsigned int) val;
2072 max = (unsigned int) max;
2073 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002074#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002075 return val > max;
2076}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002077
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002078#if defined(X32)
2079static inline int
2080is_negated_errno_x32(unsigned long long val)
2081{
2082 unsigned long long max = -(long long) nerrnos;
2083 /*
2084 * current_wordsize is 4 even in personality 0 (native X32)
2085 * but truncation _must not_ be done in it.
2086 * can't check current_wordsize here!
2087 */
2088 if (current_personality != 0) {
2089 val = (uint32_t) val;
2090 max = (uint32_t) max;
2091 }
2092 return val > max;
2093}
2094#endif
2095
Denys Vlasenko907735a2012-03-21 00:23:16 +01002096/* Returns:
2097 * 1: ok, continue in trace_syscall_exiting().
2098 * -1: error, trace_syscall_exiting() should print error indicator
2099 * ("????" etc) and bail out.
2100 */
Denys Vlasenkoc956ef02013-02-16 14:25:56 +01002101static void
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002102get_error(struct tcb *tcp)
2103{
2104 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002105 int check_errno = 1;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002106 if (tcp->s_ent->sys_flags & SYSCALL_NEVER_FAILS) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002107 check_errno = 0;
2108 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002109#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002110 if (check_errno && is_negated_errno(gpr2)) {
2111 tcp->u_rval = -1;
2112 u_error = -gpr2;
2113 }
2114 else {
2115 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002116 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002117#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002118 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002119 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002120 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002121 }
2122 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002123 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002124 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002125#elif defined(X86_64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002126 long rax;
2127 if (x86_io.iov_len == sizeof(i386_regs)) {
2128 /* Sign extend from 32 bits */
2129 rax = (int32_t)i386_regs.eax;
2130 } else {
2131 rax = x86_64_regs.rax;
2132 }
2133 if (check_errno && is_negated_errno(rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002134 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002135 u_error = -rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002136 }
2137 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002138 tcp->u_rval = rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002139 }
2140#elif defined(X32)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002141 /* In X32, return value is 64-bit (llseek uses one).
2142 * Using merely "long rax" would not work.
2143 */
2144 long long rax;
2145 if (x86_io.iov_len == sizeof(i386_regs)) {
2146 /* Sign extend from 32 bits */
2147 rax = (int32_t)i386_regs.eax;
2148 } else {
2149 rax = x86_64_regs.rax;
2150 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002151 /* Careful: is_negated_errno() works only on longs */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002152 if (check_errno && is_negated_errno_x32(rax)) {
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002153 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002154 u_error = -rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002155 }
2156 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002157 tcp->u_rval = rax; /* truncating */
2158 tcp->u_lrval = rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002159 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002160#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002161 if (ia32) {
2162 int err;
2163
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002164 err = (int)ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002165 if (check_errno && is_negated_errno(err)) {
2166 tcp->u_rval = -1;
2167 u_error = -err;
2168 }
2169 else {
2170 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002171 }
2172 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002173 if (check_errno && ia64_r10) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002174 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002175 u_error = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002176 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002177 tcp->u_rval = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002178 }
2179 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002180#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002181 if (check_errno && mips_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002182 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002183 u_error = mips_r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002184 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002185 tcp->u_rval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002186# if defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002187 tcp->u_lrval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002188# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002189 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002190#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002191 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002192 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002193 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002194 }
2195 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002196 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002197 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002198#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002199 if (check_errno && is_negated_errno(m68k_d0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002200 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002201 u_error = -m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002202 }
2203 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002204 tcp->u_rval = m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002205 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002206#elif defined(ARM) || defined(AARCH64)
2207# if defined(AARCH64)
2208 if (tcp->currpers == 1) {
2209 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2210 tcp->u_rval = -1;
2211 u_error = -aarch64_regs.regs[0];
2212 }
2213 else {
2214 tcp->u_rval = aarch64_regs.regs[0];
2215 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002216 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002217 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01002218# endif
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002219 {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002220 if (check_errno && is_negated_errno(arm_regs.ARM_r0)) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002221 tcp->u_rval = -1;
Denys Vlasenko401374e2013-02-06 18:24:39 +01002222 u_error = -arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002223 }
2224 else {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002225 tcp->u_rval = arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002226 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002227 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002228#elif defined(AVR32)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002229 if (check_errno && avr32_regs.r12 && (unsigned) -avr32_regs.r12 < nerrnos) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002230 tcp->u_rval = -1;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002231 u_error = -avr32_regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002232 }
2233 else {
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002234 tcp->u_rval = avr32_regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002235 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002236#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002237 if (check_errno && is_negated_errno(bfin_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002238 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002239 u_error = -bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002240 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002241 tcp->u_rval = bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002242 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002243#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002244 if (check_errno && alpha_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002245 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002246 u_error = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002247 }
2248 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002249 tcp->u_rval = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002250 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002251#elif defined(SPARC)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002252 if (check_errno && sparc_regs.psr & PSR_C) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002253 tcp->u_rval = -1;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002254 u_error = sparc_regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002255 }
2256 else {
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002257 tcp->u_rval = sparc_regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002258 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002259#elif defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002260 if (check_errno && sparc_regs.tstate & 0x1100000000UL) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002261 tcp->u_rval = -1;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002262 u_error = sparc_regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002263 }
2264 else {
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002265 tcp->u_rval = sparc_regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002266 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002267#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002268 if (check_errno && is_negated_errno(hppa_r28)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002269 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002270 u_error = -hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002271 }
2272 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002273 tcp->u_rval = hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002274 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002275#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002276 if (check_errno && is_negated_errno(sh_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002277 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002278 u_error = -sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002279 }
2280 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002281 tcp->u_rval = sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002282 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002283#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002284 if (check_errno && is_negated_errno(sh64_r9)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002285 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002286 u_error = -sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002287 }
2288 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002289 tcp->u_rval = sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002290 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002291#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002292 if (check_errno && cris_r10 && (unsigned) -cris_r10 < nerrnos) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002293 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002294 u_error = -cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002295 }
2296 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002297 tcp->u_rval = cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002298 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002299#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002300 /*
2301 * The standard tile calling convention returns the value (or negative
2302 * errno) in r0, and zero (or positive errno) in r1.
2303 * Until at least kernel 3.8, however, the r1 value is not reflected
2304 * in ptregs at this point, so we use r0 here.
2305 */
2306 if (check_errno && is_negated_errno(tile_regs.regs[0])) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002307 tcp->u_rval = -1;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002308 u_error = -tile_regs.regs[0];
2309 } else {
2310 tcp->u_rval = tile_regs.regs[0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002311 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002312#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002313 if (check_errno && is_negated_errno(microblaze_r3)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002314 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002315 u_error = -microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002316 }
2317 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002318 tcp->u_rval = microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002319 }
Christian Svensson492f81f2013-02-14 13:26:27 +01002320#elif defined(OR1K)
2321 if (check_errno && is_negated_errno(or1k_regs.gpr[11])) {
2322 tcp->u_rval = -1;
2323 u_error = -or1k_regs.gpr[11];
2324 }
2325 else {
2326 tcp->u_rval = or1k_regs.gpr[11];
2327 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002328#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002329 tcp->u_error = u_error;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002330}
2331
2332static void
2333dumpio(struct tcb *tcp)
2334{
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002335 int (*func)();
2336
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002337 if (syserror(tcp))
2338 return;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002339 if ((unsigned long) tcp->u_arg[0] >= MAX_QUALS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002340 return;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002341 func = tcp->s_ent->sys_func;
2342 if (func == printargs)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002343 return;
2344 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002345 if (func == sys_read ||
2346 func == sys_pread ||
2347 func == sys_recv ||
2348 func == sys_recvfrom)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002349 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002350 else if (func == sys_readv)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002351 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2352 return;
2353 }
2354 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002355 if (func == sys_write ||
2356 func == sys_pwrite ||
2357 func == sys_send ||
2358 func == sys_sendto)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002359 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002360 else if (func == sys_writev)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002361 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2362 return;
2363 }
2364}
2365
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002366static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002367trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002368{
2369 int sys_res;
2370 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002371 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002372 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002373
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002374 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002375 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002376 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002377
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002378#if SUPPORTED_PERSONALITIES > 1
2379 update_personality(tcp, tcp->currpers);
2380#endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002381 res = (get_regs_error ? -1 : get_syscall_result(tcp));
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002382 if (res == 1) {
2383 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenkoc956ef02013-02-16 14:25:56 +01002384 get_error(tcp); /* never fails */
2385 if (need_fork_exec_workarounds)
2386 syscall_fixup_for_fork_exec(tcp);
2387 if (filtered(tcp))
2388 goto ret;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002389 }
2390
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002391 if (cflag) {
2392 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002393 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002394 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002395 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002396 }
2397 }
2398
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002399 /* If not in -ff mode, and printing_tcp != tcp,
2400 * then the log currently does not end with output
2401 * of _our syscall entry_, but with something else.
2402 * We need to say which syscall's return is this.
2403 *
2404 * Forced reprinting via TCB_REPRINT is used only by
2405 * "strace -ff -oLOG test/threaded_execve" corner case.
2406 * It's the only case when -ff mode needs reprinting.
2407 */
2408 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2409 tcp->flags &= ~TCB_REPRINT;
2410 printleader(tcp);
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002411 if (tcp->qual_flg & UNDEFINED_SCNO)
Denys Vlasenko7270de52013-02-21 15:46:34 +01002412 tprintf("<... %s resumed> ", undefined_scno_name(tcp));
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002413 else
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002414 tprintf("<... %s resumed> ", tcp->s_ent->sys_name);
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002415 }
2416 printing_tcp = tcp;
2417
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002418 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002419 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002420 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002421 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002422 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002423 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002424 tcp->flags &= ~TCB_INSYSCALL;
2425 return res;
2426 }
2427
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002428 sys_res = 0;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002429 if (tcp->qual_flg & QUAL_RAW) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002430 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002431 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002432 /* FIXME: not_failing_only (IOW, option -z) is broken:
2433 * failure of syscall is known only after syscall return.
2434 * Thus we end up with something like this on, say, ENOENT:
2435 * open("doesnt_exist", O_RDONLY <unfinished ...>
2436 * {next syscall decode}
2437 * whereas the intended result is that open(...) line
2438 * is not shown at all.
2439 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002440 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002441 goto ret; /* ignore failed syscalls */
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002442 sys_res = tcp->s_ent->sys_func(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002443 }
2444
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002445 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002446 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002447 u_error = tcp->u_error;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002448 if (tcp->qual_flg & QUAL_RAW) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002449 if (u_error)
2450 tprintf("= -1 (errno %ld)", u_error);
2451 else
2452 tprintf("= %#lx", tcp->u_rval);
2453 }
2454 else if (!(sys_res & RVAL_NONE) && u_error) {
2455 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002456 /* Blocked signals do not interrupt any syscalls.
2457 * In this case syscalls don't return ERESTARTfoo codes.
2458 *
2459 * Deadly signals set to SIG_DFL interrupt syscalls
2460 * and kill the process regardless of which of the codes below
2461 * is returned by the interrupted syscall.
2462 * In some cases, kernel forces a kernel-generated deadly
2463 * signal to be unblocked and set to SIG_DFL (and thus cause
2464 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2465 * or SIGILL. (The alternative is to leave process spinning
2466 * forever on the faulty instruction - not useful).
2467 *
2468 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2469 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2470 * but kernel will always restart them.
2471 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002472 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002473 /* Most common type of signal-interrupted syscall exit code.
2474 * The system call will be restarted with the same arguments
2475 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2476 */
2477 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002478 break;
2479 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002480 /* Rare. For example, fork() returns this if interrupted.
2481 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2482 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002483 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002484 break;
2485 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002486 /* pause(), rt_sigsuspend() etc use this code.
2487 * SA_RESTART is ignored (assumed not set):
2488 * syscall won't restart (will return EINTR instead)
Denys Vlasenko30c03232013-02-19 16:59:26 +01002489 * even after signal with SA_RESTART set. However,
2490 * after SIG_IGN or SIG_DFL signal it will restart
2491 * (thus the name "restart only if has no handler").
Denys Vlasenkofe585652012-01-12 11:26:34 +01002492 */
2493 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002494 break;
2495 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002496 /* Syscalls like nanosleep(), poll() which can't be
2497 * restarted with their original arguments use this
2498 * code. Kernel will execute restart_syscall() instead,
2499 * which changes arguments before restarting syscall.
2500 * SA_RESTART is ignored (assumed not set) similarly
2501 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2502 * since restart data is saved in "restart block"
2503 * in task struct, and if signal handler uses a syscall
2504 * which in turn saves another such restart block,
2505 * old data is lost and restart becomes impossible)
2506 */
2507 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002508 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002509 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002510 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002511 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002512 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002513 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002514 strerror(u_error));
2515 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002516 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002517 strerror(u_error));
2518 break;
2519 }
2520 if ((sys_res & RVAL_STR) && tcp->auxstr)
2521 tprintf(" (%s)", tcp->auxstr);
2522 }
2523 else {
2524 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002525 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002526 else {
2527 switch (sys_res & RVAL_MASK) {
2528 case RVAL_HEX:
2529 tprintf("= %#lx", tcp->u_rval);
2530 break;
2531 case RVAL_OCTAL:
2532 tprintf("= %#lo", tcp->u_rval);
2533 break;
2534 case RVAL_UDECIMAL:
2535 tprintf("= %lu", tcp->u_rval);
2536 break;
2537 case RVAL_DECIMAL:
2538 tprintf("= %ld", tcp->u_rval);
2539 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002540#if defined(LINUX_MIPSN32) || defined(X32)
2541 /*
2542 case RVAL_LHEX:
2543 tprintf("= %#llx", tcp->u_lrval);
2544 break;
2545 case RVAL_LOCTAL:
2546 tprintf("= %#llo", tcp->u_lrval);
2547 break;
2548 */
2549 case RVAL_LUDECIMAL:
2550 tprintf("= %llu", tcp->u_lrval);
2551 break;
2552 /*
2553 case RVAL_LDECIMAL:
2554 tprintf("= %lld", tcp->u_lrval);
2555 break;
2556 */
2557#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002558 default:
2559 fprintf(stderr,
2560 "invalid rval format\n");
2561 break;
2562 }
2563 }
2564 if ((sys_res & RVAL_STR) && tcp->auxstr)
2565 tprintf(" (%s)", tcp->auxstr);
2566 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002567 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002568 tv_sub(&tv, &tv, &tcp->etime);
2569 tprintf(" <%ld.%06ld>",
2570 (long) tv.tv_sec, (long) tv.tv_usec);
2571 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002572 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002573 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002574 line_ended();
2575
Denys Vlasenko3b738812011-08-22 02:06:35 +02002576 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002577 tcp->flags &= ~TCB_INSYSCALL;
2578 return 0;
2579}
2580
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002581int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002582trace_syscall(struct tcb *tcp)
2583{
2584 return exiting(tcp) ?
2585 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2586}