blob: cd3647d0f5518fe391334c8762b004b55500bbe1 [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
Steve McIntyred8d3bd32012-10-24 17:58:16 +010068#if defined(AARCH64)
69# include <asm/ptrace.h>
70# include <sys/uio.h>
71# include <elf.h>
72#endif
73
Chris Metcalf0b99a8a2013-02-05 17:48:33 +010074#if defined(TILE)
75# ifndef PT_FLAGS_COMPAT
76# define PT_FLAGS_COMPAT 0x10000 /* from Linux 3.8 on */
77# endif
78#endif
79
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000080#ifndef ERESTARTSYS
Denys Vlasenko523635f2012-02-25 02:44:25 +010081# define ERESTARTSYS 512
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000082#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010083#ifndef ERESTARTNOINTR
Denys Vlasenko523635f2012-02-25 02:44:25 +010084# define ERESTARTNOINTR 513
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000085#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010086#ifndef ERESTARTNOHAND
87# define ERESTARTNOHAND 514 /* restart if no handler */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000088#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010089#ifndef ERESTART_RESTARTBLOCK
Denys Vlasenko523635f2012-02-25 02:44:25 +010090# define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
Roland McGrath9c555e72003-07-09 09:47:59 +000091#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010092
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000093#ifndef NSIG
Denys Vlasenko523635f2012-02-25 02:44:25 +010094# warning: NSIG is not defined, using 32
95# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000096#endif
97#ifdef ARM
Denys Vlasenko041b3ee2011-08-18 12:48:56 +020098/* Ugh. Is this really correct? ARM has no RT signals?! */
Denys Vlasenko523635f2012-02-25 02:44:25 +010099# undef NSIG
100# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000101#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000102
103#include "syscall.h"
104
105/* Define these shorthand notations to simplify the syscallent files. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000106#define TD TRACE_DESC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000107#define TF TRACE_FILE
108#define TI TRACE_IPC
109#define TN TRACE_NETWORK
110#define TP TRACE_PROCESS
111#define TS TRACE_SIGNAL
Namhyung Kim96792962012-10-24 11:41:57 +0900112#define TM TRACE_MEMORY
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000113#define NF SYSCALL_NEVER_FAILS
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200114#define MA MAX_ARGS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000115
Roland McGrathee36ce12004-09-04 03:53:10 +0000116static const struct sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000117#include "syscallent.h"
118};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000119
120#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000121static const struct sysent sysent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100122# include "syscallent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000123};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200124#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000125
126#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000127static const struct sysent sysent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100128# include "syscallent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000129};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200130#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000131
132/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000133#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000134#undef TF
135#undef TI
136#undef TN
137#undef TP
138#undef TS
Namhyung Kim96792962012-10-24 11:41:57 +0900139#undef TM
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000140#undef NF
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200141#undef MA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000142
Denys Vlasenko39fca622011-08-20 02:12:33 +0200143/*
144 * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
145 * program `ioctlsort', such that the list is sorted by the `code' field.
146 * This has the side-effect of resolving the _IO.. macros into
147 * plain integers, eliminating the need to include here everything
148 * in "/usr/include".
149 */
150
Roland McGrathee36ce12004-09-04 03:53:10 +0000151static const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000152#include "errnoent.h"
153};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200154static const char *const signalent0[] = {
155#include "signalent.h"
156};
157static const struct ioctlent ioctlent0[] = {
158#include "ioctlent.h"
159};
160enum { nsyscalls0 = ARRAY_SIZE(sysent0) };
161enum { nerrnos0 = ARRAY_SIZE(errnoent0) };
162enum { nsignals0 = ARRAY_SIZE(signalent0) };
163enum { nioctlents0 = ARRAY_SIZE(ioctlent0) };
164int qual_flags0[MAX_QUALS];
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000165
166#if SUPPORTED_PERSONALITIES >= 2
Roland McGrathee36ce12004-09-04 03:53:10 +0000167static const char *const errnoent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100168# include "errnoent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000169};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200170static const char *const signalent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100171# include "signalent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200172};
173static const struct ioctlent ioctlent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100174# include "ioctlent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200175};
176enum { nsyscalls1 = ARRAY_SIZE(sysent1) };
177enum { nerrnos1 = ARRAY_SIZE(errnoent1) };
178enum { nsignals1 = ARRAY_SIZE(signalent1) };
179enum { nioctlents1 = ARRAY_SIZE(ioctlent1) };
180int qual_flags1[MAX_QUALS];
181#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000182
183#if SUPPORTED_PERSONALITIES >= 3
Roland McGrathee36ce12004-09-04 03:53:10 +0000184static const char *const errnoent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100185# include "errnoent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000186};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200187static const char *const signalent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100188# include "signalent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200189};
190static const struct ioctlent ioctlent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100191# include "ioctlent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200192};
193enum { nsyscalls2 = ARRAY_SIZE(sysent2) };
194enum { nerrnos2 = ARRAY_SIZE(errnoent2) };
195enum { nsignals2 = ARRAY_SIZE(signalent2) };
196enum { nioctlents2 = ARRAY_SIZE(ioctlent2) };
197int qual_flags2[MAX_QUALS];
198#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000199
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100200const struct sysent *sysent = sysent0;
201const char *const *errnoent = errnoent0;
202const char *const *signalent = signalent0;
203const struct ioctlent *ioctlent = ioctlent0;
204unsigned nsyscalls = nsyscalls0;
205unsigned nerrnos = nerrnos0;
206unsigned nsignals = nsignals0;
207unsigned nioctlents = nioctlents0;
208int *qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000209
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100210#if SUPPORTED_PERSONALITIES > 1
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000211int current_personality;
212
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000213const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
214 PERSONALITY0_WORDSIZE,
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000215 PERSONALITY1_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100216# if SUPPORTED_PERSONALITIES > 2
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000217 PERSONALITY2_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100218# endif
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200219};
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000220
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200221void
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000222set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000223{
224 switch (personality) {
225 case 0:
226 errnoent = errnoent0;
227 nerrnos = nerrnos0;
228 sysent = sysent0;
229 nsyscalls = nsyscalls0;
230 ioctlent = ioctlent0;
231 nioctlents = nioctlents0;
232 signalent = signalent0;
233 nsignals = nsignals0;
Roland McGrath138c6a32006-01-12 09:50:49 +0000234 qual_flags = qual_flags0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000235 break;
236
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000237 case 1:
238 errnoent = errnoent1;
239 nerrnos = nerrnos1;
240 sysent = sysent1;
241 nsyscalls = nsyscalls1;
242 ioctlent = ioctlent1;
243 nioctlents = nioctlents1;
244 signalent = signalent1;
245 nsignals = nsignals1;
Roland McGrath138c6a32006-01-12 09:50:49 +0000246 qual_flags = qual_flags1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000247 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000248
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100249# if SUPPORTED_PERSONALITIES >= 3
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000250 case 2:
251 errnoent = errnoent2;
252 nerrnos = nerrnos2;
253 sysent = sysent2;
254 nsyscalls = nsyscalls2;
255 ioctlent = ioctlent2;
256 nioctlents = nioctlents2;
257 signalent = signalent2;
258 nsignals = nsignals2;
Roland McGrath138c6a32006-01-12 09:50:49 +0000259 qual_flags = qual_flags2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000260 break;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100261# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000262 }
263
264 current_personality = personality;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000265}
266
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000267static void
268update_personality(struct tcb *tcp, int personality)
269{
270 if (personality == current_personality)
271 return;
272 set_personality(personality);
273
274 if (personality == tcp->currpers)
275 return;
276 tcp->currpers = personality;
277
H.J. Lu35be5812012-04-16 13:00:01 +0200278# if defined(POWERPC64)
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000279 if (!qflag) {
280 static const char *const names[] = {"64 bit", "32 bit"};
281 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
282 tcp->pid, names[personality]);
283 }
H.J. Lu35be5812012-04-16 13:00:01 +0200284# elif defined(X86_64)
285 if (!qflag) {
286 static const char *const names[] = {"64 bit", "32 bit", "x32"};
287 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
288 tcp->pid, names[personality]);
289 }
H.J. Lu085e4282012-04-17 11:05:04 -0700290# elif defined(X32)
291 if (!qflag) {
292 static const char *const names[] = {"x32", "32 bit"};
293 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
294 tcp->pid, names[personality]);
295 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000296# elif defined(AARCH64)
297 if (!qflag) {
298 static const char *const names[] = {"32-bit ARM", "AArch64"};
299 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
300 tcp->pid, names[personality]);
301 }
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100302# elif defined(TILE)
303 if (!qflag) {
304 static const char *const names[] = {"64-bit", "32-bit"};
305 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
306 tcp->pid, names[personality]);
307 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100308# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000309}
310#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000311
Roland McGrath9797ceb2002-12-30 10:23:00 +0000312static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000313
Roland McGrathe10e62a2004-09-04 04:20:43 +0000314static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000315 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000316 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000317 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000318 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000319} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000320 { QUAL_TRACE, "trace", qual_syscall, "system call" },
321 { QUAL_TRACE, "t", qual_syscall, "system call" },
322 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
323 { QUAL_ABBREV, "a", qual_syscall, "system call" },
324 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
325 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
326 { QUAL_RAW, "raw", qual_syscall, "system call" },
327 { QUAL_RAW, "x", qual_syscall, "system call" },
328 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
329 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
330 { QUAL_SIGNAL, "s", qual_signal, "signal" },
331 { QUAL_FAULT, "fault", qual_fault, "fault" },
332 { QUAL_FAULT, "faults", qual_fault, "fault" },
333 { QUAL_FAULT, "m", qual_fault, "fault" },
334 { QUAL_READ, "read", qual_desc, "descriptor" },
335 { QUAL_READ, "reads", qual_desc, "descriptor" },
336 { QUAL_READ, "r", qual_desc, "descriptor" },
337 { QUAL_WRITE, "write", qual_desc, "descriptor" },
338 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
339 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000340 { 0, NULL, NULL, NULL },
341};
342
Roland McGrath9797ceb2002-12-30 10:23:00 +0000343static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000344qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000345{
Roland McGrath138c6a32006-01-12 09:50:49 +0000346 if (pers == 0 || pers < 0) {
347 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000348 qual_flags0[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000349 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000350 qual_flags0[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000351 }
352
353#if SUPPORTED_PERSONALITIES >= 2
354 if (pers == 1 || pers < 0) {
355 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000356 qual_flags1[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000357 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000358 qual_flags1[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000359 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100360#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000361
362#if SUPPORTED_PERSONALITIES >= 3
363 if (pers == 2 || pers < 0) {
364 if (not)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000365 qual_flags2[n] &= ~bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000366 else
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000367 qual_flags2[n] |= bitflag;
Roland McGrath138c6a32006-01-12 09:50:49 +0000368 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100369#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000370}
371
372static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000373qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000374{
375 int i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000376 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000377
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100378 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000379 int i = string_to_uint(s);
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000380 if (i < 0 || i >= MAX_QUALS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000381 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000382 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000383 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000384 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000385 for (i = 0; i < nsyscalls0; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000386 if (sysent0[i].sys_name &&
387 strcmp(s, sysent0[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000388 qualify_one(i, bitflag, not, 0);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000389 rc = 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000390 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000391
392#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000393 for (i = 0; i < nsyscalls1; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000394 if (sysent1[i].sys_name &&
395 strcmp(s, sysent1[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000396 qualify_one(i, bitflag, not, 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000397 rc = 0;
398 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100399#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000400
401#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000402 for (i = 0; i < nsyscalls2; i++)
Dmitry V. Levin4372cc92012-03-26 14:14:50 +0000403 if (sysent2[i].sys_name &&
404 strcmp(s, sysent2[i].sys_name) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000405 qualify_one(i, bitflag, not, 2);
Roland McGrath138c6a32006-01-12 09:50:49 +0000406 rc = 0;
407 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100408#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000409
Roland McGrathfe6b3522005-02-02 04:40:11 +0000410 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000411}
412
413static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000414qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000415{
416 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000417
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100418 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000419 int signo = string_to_uint(s);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000420 if (signo < 0 || signo >= MAX_QUALS)
421 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000422 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000423 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000424 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000425 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000426 s += 3;
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100427 for (i = 0; i <= NSIG; i++) {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000428 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000429 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000430 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000431 }
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100432 }
Roland McGrath76421df2005-02-02 03:51:18 +0000433 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000434}
435
436static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000437qual_fault(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000438{
439 return -1;
440}
441
442static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000443qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000444{
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100445 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000446 int desc = string_to_uint(s);
Roland McGrathfe6b3522005-02-02 04:40:11 +0000447 if (desc < 0 || desc >= MAX_QUALS)
448 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000449 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000450 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000451 }
452 return -1;
453}
454
455static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000456lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000457{
458 if (strcmp(s, "file") == 0)
459 return TRACE_FILE;
460 if (strcmp(s, "ipc") == 0)
461 return TRACE_IPC;
462 if (strcmp(s, "network") == 0)
463 return TRACE_NETWORK;
464 if (strcmp(s, "process") == 0)
465 return TRACE_PROCESS;
466 if (strcmp(s, "signal") == 0)
467 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000468 if (strcmp(s, "desc") == 0)
469 return TRACE_DESC;
Namhyung Kim96792962012-10-24 11:41:57 +0900470 if (strcmp(s, "memory") == 0)
471 return TRACE_MEMORY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000472 return -1;
473}
474
475void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000476qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000477{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000478 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000479 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000480 char *copy;
481 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000482 int i, n;
483
484 opt = &qual_options[0];
485 for (i = 0; (p = qual_options[i].option_name); i++) {
486 n = strlen(p);
487 if (strncmp(s, p, n) == 0 && s[n] == '=') {
488 opt = &qual_options[i];
489 s += n + 1;
490 break;
491 }
492 }
493 not = 0;
494 if (*s == '!') {
495 not = 1;
496 s++;
497 }
498 if (strcmp(s, "none") == 0) {
499 not = 1 - not;
500 s = "all";
501 }
502 if (strcmp(s, "all") == 0) {
503 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000504 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000505 }
506 return;
507 }
508 for (i = 0; i < MAX_QUALS; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000509 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000510 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200511 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200512 if (!copy)
513 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000514 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000515 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000516 for (i = 0; i < nsyscalls0; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000517 if (sysent0[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000518 qualify_one(i, opt->bitflag, not, 0);
Roland McGrath138c6a32006-01-12 09:50:49 +0000519
520#if SUPPORTED_PERSONALITIES >= 2
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000521 for (i = 0; i < nsyscalls1; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000522 if (sysent1[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000523 qualify_one(i, opt->bitflag, not, 1);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100524#endif
Roland McGrath138c6a32006-01-12 09:50:49 +0000525
526#if SUPPORTED_PERSONALITIES >= 3
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000527 for (i = 0; i < nsyscalls2; i++)
Roland McGrath138c6a32006-01-12 09:50:49 +0000528 if (sysent2[i].sys_flags & n)
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000529 qualify_one(i, opt->bitflag, not, 2);
Denys Vlasenko523635f2012-02-25 02:44:25 +0100530#endif
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000531
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000532 continue;
533 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000534 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100535 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000536 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000537 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000538 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000539 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000540 return;
541}
542
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000543#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000544static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000545decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000546{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000547 unsigned long addr;
548 unsigned int i, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000549
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000550 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
551 return;
552
553 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
554 addr = tcp->u_arg[1];
555 tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100556 size = current_wordsize;
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000557 for (i = 0; i < tcp->u_nargs; ++i) {
558 if (size == sizeof(int)) {
559 unsigned int arg;
560 if (umove(tcp, addr, &arg) < 0)
561 arg = 0;
562 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000563 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000564 else {
565 unsigned long arg;
566 if (umove(tcp, addr, &arg) < 0)
567 arg = 0;
568 tcp->u_arg[i] = arg;
569 }
570 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000571 }
572}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000573#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400574
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000575#ifdef SYS_ipc_subcall
576static void
577decode_ipc_subcall(struct tcb *tcp)
578{
579 unsigned int i;
580
581 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
582 return;
583
584 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
585 tcp->u_nargs = sysent[tcp->scno].nargs;
586 for (i = 0; i < tcp->u_nargs; i++)
587 tcp->u_arg[i] = tcp->u_arg[i + 1];
588}
589#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000590
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200591int
592printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000593{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200594 if (entering(tcp)) {
595 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000596
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200597 for (i = 0; i < tcp->u_nargs; i++)
598 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
599 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000600 return 0;
601}
602
Denys Vlasenko72879c62012-02-27 14:18:02 +0100603int
604printargs_lu(struct tcb *tcp)
605{
606 if (entering(tcp)) {
607 int i;
608
609 for (i = 0; i < tcp->u_nargs; i++)
610 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
611 }
612 return 0;
613}
614
615int
616printargs_ld(struct tcb *tcp)
617{
618 if (entering(tcp)) {
619 int i;
620
621 for (i = 0; i < tcp->u_nargs; i++)
622 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
623 }
624 return 0;
625}
626
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100627#if defined(SPARC) || defined(SPARC64) || defined(IA64) || defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200628long
629getrval2(struct tcb *tcp)
630{
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100631 long val;
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200632
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100633# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200634 val = regs.u_regs[U_REG_O1];
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100635# elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200636 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
637 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100638# elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200639 if (upeek(tcp, PT_R9, &val) < 0)
640 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100641# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200642
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200643 return val;
644}
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100645#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200646
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200647int
648is_restart_error(struct tcb *tcp)
649{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200650 switch (tcp->u_error) {
651 case ERESTARTSYS:
652 case ERESTARTNOINTR:
653 case ERESTARTNOHAND:
654 case ERESTART_RESTARTBLOCK:
655 return 1;
656 default:
657 break;
658 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200659 return 0;
660}
661
Denys Vlasenko523635f2012-02-25 02:44:25 +0100662#if defined(I386)
Denys Vlasenkob11322f2012-01-10 16:40:35 +0100663struct pt_regs i386_regs;
H.J. Lu35be5812012-04-16 13:00:01 +0200664#elif defined(X86_64) || defined(X32)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100665/*
666 * On 32 bits, pt_regs and user_regs_struct are the same,
667 * but on 64 bits, user_regs_struct has six more fields:
668 * fs_base, gs_base, ds, es, fs, gs.
669 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
670 */
671static struct user_regs_struct x86_64_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100672#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200673long r8, r10, psr; /* TODO: make static? */
674long ia32 = 0; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100675#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +0100676static long ppc_result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100677#elif defined(M68K)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200678static long d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100679#elif defined(BFIN)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200680static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100681#elif defined(ARM)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100682struct pt_regs regs; /* not static */
Steve McIntyred8d3bd32012-10-24 17:58:16 +0100683#elif defined(AARCH64)
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000684static struct user_pt_regs aarch64_regs;
685static struct arm_pt_regs regs;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100686static struct iovec aarch64_io = {
687 .iov_base = &aarch64_regs
688};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100689#elif defined(ALPHA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200690static long r0;
691static long a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100692#elif defined(AVR32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200693static struct pt_regs regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100694#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100695struct pt_regs regs; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100696#elif defined(LINUX_MIPSN32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200697static long long a3;
698static long long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100699#elif defined(MIPS)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200700static long a3;
701static long r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100702#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200703static long gpr2;
704static long pc;
705static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100706#elif defined(HPPA)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200707static long r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100708#elif defined(SH)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200709static long r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100710#elif defined(SH64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200711static long r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100712#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200713static long r10;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100714#elif defined(TILE)
715struct pt_regs tile_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100716#elif defined(MICROBLAZE)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200717static long r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100718#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000719
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100720void
721printcall(struct tcb *tcp)
722{
723#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
724 sizeof(long) == 8 ? "[????????????????] " : \
725 NULL /* crash */)
726 if (get_regs_error) {
727 PRINTBADPC;
728 return;
729 }
730#if defined(I386)
731 tprintf("[%08lx] ", i386_regs.eip);
732#elif defined(S390) || defined(S390X)
733 long psw;
734 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
735 PRINTBADPC;
736 return;
737 }
738# ifdef S390
739 tprintf("[%08lx] ", psw);
740# elif S390X
741 tprintf("[%16lx] ", psw);
742# endif
743#elif defined(X86_64) || defined(X32)
744 tprintf("[%16lx] ", x86_64_regs.ip);
745#elif defined(IA64)
746 long ip;
747
748 if (upeek(tcp, PT_B0, &ip) < 0) {
749 PRINTBADPC;
750 return;
751 }
752 tprintf("[%08lx] ", ip);
753#elif defined(POWERPC)
754 long pc;
755
756 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
757 PRINTBADPC;
758 return;
759 }
760# ifdef POWERPC64
761 tprintf("[%016lx] ", pc);
762# else
763 tprintf("[%08lx] ", pc);
764# endif
765#elif defined(M68K)
766 long pc;
767
768 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
769 tprints("[????????] ");
770 return;
771 }
772 tprintf("[%08lx] ", pc);
773#elif defined(ALPHA)
774 long pc;
775
776 if (upeek(tcp, REG_PC, &pc) < 0) {
777 tprints("[????????????????] ");
778 return;
779 }
780 tprintf("[%08lx] ", pc);
781#elif defined(SPARC)
782 tprintf("[%08lx] ", regs.pc);
783#elif defined(SPARC64)
784 tprintf("[%08lx] ", regs.tpc);
785#elif defined(HPPA)
786 long pc;
787
788 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
789 tprints("[????????] ");
790 return;
791 }
792 tprintf("[%08lx] ", pc);
793#elif defined(MIPS)
794 long pc;
795
796 if (upeek(tcp, REG_EPC, &pc) < 0) {
797 tprints("[????????] ");
798 return;
799 }
800 tprintf("[%08lx] ", pc);
801#elif defined(SH)
802 long pc;
803
804 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
805 tprints("[????????] ");
806 return;
807 }
808 tprintf("[%08lx] ", pc);
809#elif defined(SH64)
810 long pc;
811
812 if (upeek(tcp, REG_PC, &pc) < 0) {
813 tprints("[????????????????] ");
814 return;
815 }
816 tprintf("[%08lx] ", pc);
817#elif defined(ARM)
818 tprintf("[%08lx] ", regs.ARM_pc);
819/*#elif defined(AARCH64) ??? */
820#elif defined(AVR32)
821 tprintf("[%08lx] ", regs.pc);
822#elif defined(BFIN)
823 long pc;
824
825 if (upeek(tcp, PT_PC, &pc) < 0) {
826 PRINTBADPC;
827 return;
828 }
829 tprintf("[%08lx] ", pc);
830#elif defined(CRISV10)
831 long pc;
832
833 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
834 PRINTBADPC;
835 return;
836 }
837 tprintf("[%08lx] ", pc);
838#elif defined(CRISV32)
839 long pc;
840
841 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
842 PRINTBADPC;
843 return;
844 }
845 tprintf("[%08lx] ", pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100846#elif defined(TILE)
847# ifdef _LP64
848 tprintf("[%16lx] ", tile_regs.pc);
849# else
850 tprintf("[%08lx] ", tile_regs.pc);
851# endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100852#endif /* architecture */
853}
854
855#ifndef get_regs
856long get_regs_error;
857void get_regs(pid_t pid)
858{
859# if defined(AVR32)
860 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
861# elif defined(I386)
862 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &i386_regs);
863# elif defined(X86_64) || defined(X32)
864 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &x86_64_regs);
865# elif defined(AARCH64)
866 /*aarch64_io.iov_base = &aarch64_regs; - already is */
867 aarch64_io.iov_len = sizeof(aarch64_regs);
868 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void *)&aarch64_io);
869 if (get_regs_error)
870 return;
871 switch (aarch64_io.iov_len) {
872 case sizeof(regs):
873 /* We are in 32-bit mode */
874 memcpy(&regs, &aarch64_regs, sizeof(regs));
875 break;
876 case sizeof(aarch64_regs):
877 /* We are in 64-bit mode */
878 /* Data is already in aarch64_regs */
879 break;
880 default:
881 get_regs_error = -1;
882 break;
883 }
884# elif defined(ARM)
885 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (void *)&regs);
886# elif defined(SPARC) || defined(SPARC64)
887 get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&regs, 0);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100888# elif defined(TILE)
889 get_regs_error = ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &tile_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100890# endif
891}
892#endif
893
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200894/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +0100895 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
896 * 1: ok, continue in trace_syscall_entering().
897 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +0200898 * ("????" etc) and bail out.
899 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100900static int
Denys Vlasenko06602d92011-08-24 17:53:52 +0200901get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000902{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000903 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000904
Denys Vlasenko523635f2012-02-25 02:44:25 +0100905#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000906 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200907 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +0000908
909 if (syscall_mode != -ENOSYS) {
910 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000911 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +0000912 */
913 scno = syscall_mode;
914 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000915 /*
Michal Ludvig882eda82002-11-11 12:50:47 +0000916 * Old style of "passing" the scno via the SVC instruction.
917 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000918 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200919 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +0200920 static const int gpr_offset[16] = {
921 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
922 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
923 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
924 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
925 };
Roland McGrath761b5d72002-12-15 23:58:31 +0000926
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000927 if (upeek(tcp, PT_PSWADDR, &pc) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +0000928 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000929 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +0000930 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +0000931 if (errno) {
Dmitry V. Levin9a71bcd2012-09-17 23:20:54 +0000932 perror_msg("%s", "peektext(pc-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +0000933 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +0000934 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000935
936 /*
937 * We have to check if the SVC got executed directly or via an
938 * EXECUTE instruction. In case of EXECUTE it is necessary to do
939 * instruction decoding to derive the system call number.
940 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
941 * so that this doesn't work if a SVC opcode is part of an EXECUTE
942 * opcode. Since there is no way to find out the opcode size this
943 * is the best we can do...
944 */
Michal Ludvig882eda82002-11-11 12:50:47 +0000945 if ((opcode & 0xff00) == 0x0a00) {
946 /* SVC opcode */
947 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +0000948 }
Michal Ludvig882eda82002-11-11 12:50:47 +0000949 else {
950 /* SVC got executed by EXECUTE instruction */
951
952 /*
953 * Do instruction decoding of EXECUTE. If you really want to
954 * understand this, read the Principles of Operations.
955 */
956 svc_addr = (void *) (opcode & 0xfff);
957
958 tmp = 0;
959 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000960 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000961 return -1;
962 svc_addr += tmp;
963
964 tmp = 0;
965 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000966 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000967 return -1;
968 svc_addr += tmp;
969
Denys Vlasenkofb036672009-01-23 16:30:26 +0000970 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +0000971 if (errno)
972 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100973# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +0000974 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100975# else
Michal Ludvig882eda82002-11-11 12:50:47 +0000976 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100977# endif
Michal Ludvig882eda82002-11-11 12:50:47 +0000978 tmp = 0;
979 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000980 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +0000981 return -1;
982
983 scno = (scno | tmp) & 0xff;
984 }
985 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100986#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +0000987 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000988 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100989# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200990 /* TODO: speed up strace by not doing this at every syscall.
991 * We only need to do it after execve.
992 */
993 int currpers;
994 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +0200995
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +0200996 /* Check for 64/32 bit mode. */
997 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
998 return -1;
999 /* SF is bit 0 of MSR */
1000 if (val < 0)
1001 currpers = 0;
1002 else
1003 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001004 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001005# endif
1006#elif defined(AVR32)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001007 scno = regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001008#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001009 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001010 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001011#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001012 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +02001013#elif defined(X86_64) || defined(X32)
1014# ifndef __X32_SYSCALL_BIT
1015# define __X32_SYSCALL_BIT 0x40000000
1016# endif
1017# ifndef __X32_SYSCALL_MASK
1018# define __X32_SYSCALL_MASK __X32_SYSCALL_BIT
1019# endif
1020
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001021 int currpers;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001022 scno = x86_64_regs.orig_rax;
Michal Ludvig0e035502002-09-23 15:41:01 +00001023
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001024 /* Check CS register value. On x86-64 linux it is:
1025 * 0x33 for long mode (64 bit)
1026 * 0x23 for compatibility mode (32 bit)
H.J. Lu35be5812012-04-16 13:00:01 +02001027 * Check DS register value. On x86-64 linux it is:
1028 * 0x2b for x32 mode (x86-64 in 32 bit)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001029 */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001030 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001031 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +02001032 case 0x33:
1033 if (x86_64_regs.ds == 0x2b) {
1034 currpers = 2;
1035 scno &= ~__X32_SYSCALL_MASK;
1036 } else
1037 currpers = 0;
1038 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001039 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001040 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001041 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001042 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001043 currpers = current_personality;
1044 break;
1045 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001046# if 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001047 /* This version analyzes the opcode of a syscall instruction.
1048 * (int 0x80 on i386 vs. syscall on x86-64)
1049 * It works, but is too complicated.
1050 */
1051 unsigned long val, rip, i;
Michal Ludvig0e035502002-09-23 15:41:01 +00001052
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001053 rip = x86_64_regs.rip;
Roland McGrath761b5d72002-12-15 23:58:31 +00001054
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001055 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
1056 rip -= 2;
1057 errno = 0;
Michal Ludvig0e035502002-09-23 15:41:01 +00001058
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001059 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001060 if (errno)
1061 fprintf(stderr, "ptrace_peektext failed: %s\n",
1062 strerror(errno));
1063 switch (call & 0xffff) {
1064 /* x86-64: syscall = 0x0f 0x05 */
1065 case 0x050f: currpers = 0; break;
1066 /* i386: int 0x80 = 0xcd 0x80 */
1067 case 0x80cd: currpers = 1; break;
1068 default:
1069 currpers = current_personality;
1070 fprintf(stderr,
1071 "Unknown syscall opcode (0x%04X) while "
1072 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001073 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001074 break;
1075 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001076# endif
H.J. Lu35be5812012-04-16 13:00:01 +02001077# ifdef X32
H.J. Lu085e4282012-04-17 11:05:04 -07001078 /* Value of currpers:
1079 * 0: 64 bit
1080 * 1: 32 bit
1081 * 2: X32
1082 * Value of current_personality:
1083 * 0: X32
1084 * 1: 32 bit
1085 */
1086 switch (currpers) {
1087 case 0:
1088 fprintf(stderr, "syscall_%lu (...) in unsupported "
1089 "64-bit mode of process PID=%d\n",
1090 scno, tcp->pid);
1091 return 0;
1092 case 2:
1093 currpers = 0;
H.J. Lu35be5812012-04-16 13:00:01 +02001094 }
H.J. Lu35be5812012-04-16 13:00:01 +02001095# endif
H.J. Lu085e4282012-04-17 11:05:04 -07001096 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001097#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001098# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001099 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001100 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001101 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001102 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001103 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001104 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001105 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001106 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001107 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001108#elif defined(AARCH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001109 switch (aarch64_io.iov_len) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001110 case sizeof(aarch64_regs):
1111 /* We are in 64-bit mode */
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001112 scno = aarch64_regs.regs[8];
1113 update_personality(tcp, 1);
1114 break;
1115 case sizeof(regs):
1116 /* We are in 32-bit mode */
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001117 scno = regs.uregs[7];
1118 update_personality(tcp, 0);
1119 break;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001120 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001121#elif defined(ARM)
Roland McGrath0f87c492003-06-03 23:29:04 +00001122 /*
1123 * We only need to grab the syscall number on syscall entry.
1124 */
1125 if (regs.ARM_ip == 0) {
1126 /*
1127 * Note: we only deal with only 32-bit CPUs here.
1128 */
1129 if (regs.ARM_cpsr & 0x20) {
1130 /*
1131 * Get the Thumb-mode system call number
1132 */
1133 scno = regs.ARM_r7;
1134 } else {
1135 /*
1136 * Get the ARM-mode system call number
1137 */
1138 errno = 0;
Denys Vlasenkofb036672009-01-23 16:30:26 +00001139 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
Roland McGrath0f87c492003-06-03 23:29:04 +00001140 if (errno)
1141 return -1;
1142
Roland McGrathf691bd22006-04-25 07:34:41 +00001143 /* Handle the EABI syscall convention. We do not
1144 bother converting structures between the two
1145 ABIs, but basic functionality should work even
1146 if strace and the traced program have different
1147 ABIs. */
1148 if (scno == 0xef000000) {
1149 scno = regs.ARM_r7;
1150 } else {
1151 if ((scno & 0x0ff00000) != 0x0f900000) {
1152 fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1153 scno);
1154 return -1;
1155 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001156
Roland McGrathf691bd22006-04-25 07:34:41 +00001157 /*
1158 * Fixup the syscall number
1159 */
1160 scno &= 0x000fffff;
1161 }
Roland McGrath0f87c492003-06-03 23:29:04 +00001162 }
Roland McGrath56703312008-05-20 01:35:55 +00001163 if (scno & 0x0f0000) {
1164 /*
1165 * Handle ARM specific syscall
1166 */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001167 update_personality(tcp, 1);
Roland McGrath56703312008-05-20 01:35:55 +00001168 scno &= 0x0000ffff;
1169 } else
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001170 update_personality(tcp, 0);
Roland McGrath0f87c492003-06-03 23:29:04 +00001171
Roland McGrath0f87c492003-06-03 23:29:04 +00001172 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001173 fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1174 tcp->flags |= TCB_INSYSCALL;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001175 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001176#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001177 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001178 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001179#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001180 unsigned long long regs[38];
1181
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001182 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001183 return -1;
1184 a3 = regs[REG_A3];
1185 r2 = regs[REG_V0];
1186
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001187 scno = r2;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001188 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001189 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001190 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001191 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001192 return 0;
1193 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001194 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001195#elif defined(MIPS)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001196 if (upeek(tcp, REG_A3, &a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001197 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001198 if (upeek(tcp, REG_V0, &scno) < 0)
1199 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001200
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001201 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001202 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001203 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001204 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001205 return 0;
1206 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001207 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001208#elif defined(ALPHA)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001209 if (upeek(tcp, REG_A3, &a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001210 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001211 if (upeek(tcp, REG_R0, &scno) < 0)
1212 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001213
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001214 /*
1215 * Do some sanity checks to figure out if it's
1216 * really a syscall entry
1217 */
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001218 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001219 if (a3 == 0 || a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001220 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001221 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001222 return 0;
1223 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001224 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001225#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001226 /* Disassemble the syscall trap. */
1227 /* Retrieve the syscall trap instruction. */
Denys Vlasenko46455822013-02-05 17:02:59 +01001228 unsigned long trap;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001229 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001230# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001231 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1232 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001233# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001234 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001235# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001236 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001237 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001238
1239 /* Disassemble the trap to see what personality to use. */
1240 switch (trap) {
1241 case 0x91d02010:
1242 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001243 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001244 break;
1245 case 0x91d0206d:
1246 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001247 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001248 break;
1249 case 0x91d02000:
1250 /* SunOS syscall trap. (pers 1) */
1251 fprintf(stderr, "syscall: SunOS no support\n");
1252 return -1;
1253 case 0x91d02008:
1254 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001255 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001256 break;
1257 case 0x91d02009:
1258 /* NetBSD/FreeBSD syscall trap. */
1259 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1260 return -1;
1261 case 0x91d02027:
1262 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001263 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001264 break;
1265 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001266# if defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001267 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001268# else
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001269 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001270# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001271 return -1;
1272 }
1273
1274 /* Extract the system call number from the registers. */
1275 if (trap == 0x91d02027)
1276 scno = 156;
1277 else
1278 scno = regs.u_regs[U_REG_G1];
1279 if (scno == 0) {
1280 scno = regs.u_regs[U_REG_O0];
1281 memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1282 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001283#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001284 if (upeek(tcp, PT_GR20, &scno) < 0)
1285 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001286#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001287 /*
1288 * In the new syscall ABI, the system call number is in R3.
1289 */
1290 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1291 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001292
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001293 if (scno < 0) {
1294 /* Odd as it may seem, a glibc bug has been known to cause
1295 glibc to issue bogus negative syscall numbers. So for
1296 our purposes, make strace print what it *should* have been */
1297 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001298 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001299 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001300 "Detected glibc bug: bogus system call"
1301 " number = %ld, correcting to %ld\n",
1302 scno,
1303 correct_scno);
1304 scno = correct_scno;
1305 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001306#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001307 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001308 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001309 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001310#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001311 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1312 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001313#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001314 int currpers;
1315 scno = tile_regs.regs[10];
1316# ifdef __tilepro__
1317 currpers = 1;
1318# else
1319 if (tile_regs.flags & PT_FLAGS_COMPAT)
1320 currpers = 1;
1321 else
1322 currpers = 0;
1323# endif
1324 update_personality(tcp, currpers);
1325
1326 if (!(tcp->flags & TCB_INSYSCALL)) {
1327 /* Check if we return from execve. */
1328 if (tcp->flags & TCB_WAITEXECVE) {
1329 tcp->flags &= ~TCB_WAITEXECVE;
1330 return 0;
1331 }
1332 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001333#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001334 if (upeek(tcp, 0, &scno) < 0)
1335 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001336#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001337
Denys Vlasenko523635f2012-02-25 02:44:25 +01001338#if defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001339 /* new syscall ABI returns result in R0 */
1340 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1341 return -1;
Roland McGrathf5a47772003-06-26 22:40:42 +00001342#elif defined(SH64)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001343 /* ABI defines result returned in r9 */
1344 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1345 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001346#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001347
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001348 tcp->scno = scno;
Pavel Machek4dc3b142000-02-01 17:58:41 +00001349 return 1;
1350}
1351
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001352/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001353 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001354 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1355 * 1: ok, continue in trace_syscall_entering().
1356 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001357 * ("????" etc) and bail out.
1358 */
Roland McGratha4d48532005-06-08 20:45:28 +00001359static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001360syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001361{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001362 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001363#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001364 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001365 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001366 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1367 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001368 }
H.J. Lu35be5812012-04-16 13:00:01 +02001369#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001370 {
1371 long rax = x86_64_regs.rax;
Denys Vlasenko18beb982011-08-24 16:59:23 +02001372 if (current_personality == 1)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001373 rax = (int)rax; /* sign extend from 32 bits */
1374 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001375 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001376 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1377 return 0;
1378 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001379 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001380#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001381 /* TODO: we already fetched PT_GPR2 in get_scno
1382 * and stored it in syscall_mode, reuse it here
1383 * instead of re-fetching?
1384 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001385 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001386 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001387 if (syscall_mode != -ENOSYS)
1388 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001389 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001390 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001391 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001392 return 0;
1393 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001394#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001395 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001396 if (upeek(tcp, 4*PT_D0, &d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001397 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001398 if (d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001399 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001400 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001401 return 0;
1402 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001403#elif defined(IA64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001404 if (upeek(tcp, PT_R10, &r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001405 return -1;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001406 if (upeek(tcp, PT_R8, &r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001407 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001408 if (ia32 && r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001409 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001410 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001411 return 0;
1412 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001413#elif defined(CRISV10) || defined(CRISV32)
Edgar E. Iglesiaseeb9ce32009-10-05 14:41:02 +00001414 if (upeek(tcp, 4*PT_R10, &r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001415 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001416 if (r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001417 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001418 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001419 return 0;
1420 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001421#elif defined(MICROBLAZE)
1422 if (upeek(tcp, 3 * 4, &r3) < 0)
1423 return -1;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001424 if (r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001425 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001426 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001427 return 0;
1428 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001429#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001430 return 1;
1431}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001432
Denys Vlasenko146b9442012-03-18 22:10:48 +01001433static void
1434internal_fork(struct tcb *tcp)
1435{
1436#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1437# define ARG_FLAGS 1
1438#else
1439# define ARG_FLAGS 0
1440#endif
1441#ifndef CLONE_UNTRACED
1442# define CLONE_UNTRACED 0x00800000
1443#endif
1444 if ((ptrace_setoptions
1445 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1446 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1447 return;
1448
1449 if (!followfork)
1450 return;
1451
1452 if (entering(tcp)) {
1453 /*
1454 * We won't see the new child if clone is called with
1455 * CLONE_UNTRACED, so we keep the same logic with that option
1456 * and don't trace it.
1457 */
1458 if ((sysent[tcp->scno].sys_func == sys_clone) &&
1459 (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1460 return;
1461 setbpt(tcp);
1462 } else {
1463 if (tcp->flags & TCB_BPTSET)
1464 clearbpt(tcp);
1465 }
1466}
1467
1468#if defined(TCB_WAITEXECVE)
1469static void
1470internal_exec(struct tcb *tcp)
1471{
1472 /* Maybe we have post-execve SIGTRAP suppressed? */
1473 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1474 return; /* yes, no need to do anything */
1475
1476 if (exiting(tcp) && syserror(tcp))
1477 /* Error in execve, no post-execve SIGTRAP expected */
1478 tcp->flags &= ~TCB_WAITEXECVE;
1479 else
1480 tcp->flags |= TCB_WAITEXECVE;
1481}
1482#endif
1483
1484static void
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001485internal_syscall(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001486{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001487 /*
1488 * We must always trace a few critical system calls in order to
1489 * correctly support following forks in the presence of tracing
1490 * qualifiers.
1491 */
1492 int (*func)();
1493
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001494 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenko146b9442012-03-18 22:10:48 +01001495 return;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001496
1497 func = sysent[tcp->scno].sys_func;
1498
1499 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001500 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001501 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001502 ) {
1503 internal_fork(tcp);
1504 return;
1505 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001506
Denys Vlasenko84703742012-02-25 02:38:52 +01001507#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001508 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001509# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001510 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001511# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001512 ) {
1513 internal_exec(tcp);
1514 return;
1515 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001516#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001517}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001518
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001519/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001520static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001521get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001522{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001523 int i, nargs;
1524
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001525 if (SCNO_IN_RANGE(tcp->scno))
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001526 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001527 else
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001528 nargs = tcp->u_nargs = MAX_ARGS;
1529
Denys Vlasenko523635f2012-02-25 02:44:25 +01001530#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001531 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001532 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1533 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001534#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001535 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001536 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1537 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001538#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001539 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001540 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001541 long rbs_end;
1542 /* be backwards compatible with kernel < 2.4.4... */
1543# ifndef PT_RBS_END
1544# define PT_RBS_END PT_AR_BSP
1545# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001546
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001547 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1548 return -1;
1549 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001550 return -1;
1551
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001552 sof = (cfm >> 0) & 0x7f;
1553 sol = (cfm >> 7) & 0x7f;
1554 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1555
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001556 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001557 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1558 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1559 return -1;
1560 }
1561 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001562 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1563 PT_R9 /* ECX = out1 */,
1564 PT_R10 /* EDX = out2 */,
1565 PT_R14 /* ESI = out3 */,
1566 PT_R15 /* EDI = out4 */,
1567 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001568
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001569 for (i = 0; i < nargs; ++i) {
1570 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1571 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001572 /* truncate away IVE sign-extension */
1573 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001574 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001575 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001576#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001577 /* N32 and N64 both use up to six registers. */
1578 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001579
1580 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1581 return -1;
1582
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001583 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001584 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001585# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001586 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001587# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001588 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001589#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001590 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001591 long sp;
1592
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001593 if (upeek(tcp, REG_SP, &sp) < 0)
1594 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001595 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001596 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1597 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001598 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001599 (char *)(tcp->u_arg + 4));
1600 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001601 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001602 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001603 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001604 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001605#elif defined(POWERPC)
1606# ifndef PT_ORIG_R3
1607# define PT_ORIG_R3 34
1608# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001609 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001610 if (upeek(tcp, (i==0) ?
1611 (sizeof(unsigned long) * PT_ORIG_R3) :
1612 ((i+PT_R3) * sizeof(unsigned long)),
1613 &tcp->u_arg[i]) < 0)
1614 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001615 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001616#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001617 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001618 tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001619#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001620 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001621 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1622 return -1;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001623#elif defined(ARM) || defined(AARCH64)
1624# if defined(AARCH64)
1625 if (tcp->currpers == 1)
1626 for (i = 0; i < nargs; ++i)
1627 tcp->u_arg[i] = aarch64_regs.regs[i];
1628 else
1629# endif /* AARCH64 */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001630 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001631 tcp->u_arg[i] = regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001632#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001633 (void)i;
1634 (void)nargs;
1635 tcp->u_arg[0] = regs.r12;
1636 tcp->u_arg[1] = regs.r11;
1637 tcp->u_arg[2] = regs.r10;
1638 tcp->u_arg[3] = regs.r9;
1639 tcp->u_arg[4] = regs.r5;
1640 tcp->u_arg[5] = regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001641#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001642 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 +02001643
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001644 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001645 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1646 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001647#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001648 static const int syscall_regs[MAX_ARGS] = {
1649 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1650 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001651 };
1652
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001653 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001654 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001655 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001656#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001657 int i;
1658 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001659 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001660
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001661 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001662 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1663 return -1;
H.J. Lu35be5812012-04-16 13:00:01 +02001664#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001665 (void)i;
1666 (void)nargs;
H.J. Lu35be5812012-04-16 13:00:01 +02001667 if (current_personality != 1) { /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001668 tcp->u_arg[0] = x86_64_regs.rdi;
1669 tcp->u_arg[1] = x86_64_regs.rsi;
1670 tcp->u_arg[2] = x86_64_regs.rdx;
1671 tcp->u_arg[3] = x86_64_regs.r10;
1672 tcp->u_arg[4] = x86_64_regs.r8;
1673 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001674# ifdef X32
1675 tcp->ext_arg[0] = x86_64_regs.rdi;
1676 tcp->ext_arg[1] = x86_64_regs.rsi;
1677 tcp->ext_arg[2] = x86_64_regs.rdx;
1678 tcp->ext_arg[3] = x86_64_regs.r10;
1679 tcp->ext_arg[4] = x86_64_regs.r8;
1680 tcp->ext_arg[5] = x86_64_regs.r9;
1681# endif
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001682 } else { /* i386 ABI */
1683 /* Sign-extend lower 32 bits */
1684 tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1685 tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1686 tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1687 tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1688 tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1689 tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1690 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001691#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001692 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001693 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1694 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001695#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001696 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001697 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001698 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001699 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001700
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001701 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001702 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1703 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001704#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001705 for (i = 0; i < nargs; ++i)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001706 tcp->u_arg[i] = tile_regs.regs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001707#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001708 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001709 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1710 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001711#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001712 (void)i;
1713 (void)nargs;
1714 tcp->u_arg[0] = i386_regs.ebx;
1715 tcp->u_arg[1] = i386_regs.ecx;
1716 tcp->u_arg[2] = i386_regs.edx;
1717 tcp->u_arg[3] = i386_regs.esi;
1718 tcp->u_arg[4] = i386_regs.edi;
1719 tcp->u_arg[5] = i386_regs.ebp;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001720#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001721 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001722 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1723 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001724#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001725 return 1;
1726}
1727
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001728static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001729trace_syscall_entering(struct tcb *tcp)
1730{
1731 int res, scno_good;
1732
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001733#if defined TCB_WAITEXECVE
1734 if (tcp->flags & TCB_WAITEXECVE) {
1735 /* This is the post-execve SIGTRAP. */
1736 tcp->flags &= ~TCB_WAITEXECVE;
1737 return 0;
1738 }
1739#endif
1740
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001741 scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001742 if (res == 0)
1743 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001744 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001745 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001746 if (res == 0)
1747 return res;
1748 if (res == 1)
1749 res = get_syscall_args(tcp);
1750 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001751
1752 if (res != 1) {
1753 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001754 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001755 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001756 else if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001757 tprintf("syscall_%lu(", tcp->scno);
1758 else
1759 tprintf("%s(", sysent[tcp->scno].sys_name);
1760 /*
1761 * " <unavailable>" will be added later by the code which
1762 * detects ptrace errors.
1763 */
1764 goto ret;
1765 }
1766
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001767#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1768 while (SCNO_IN_RANGE(tcp->scno)) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001769# ifdef SYS_socket_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001770 if (sysent[tcp->scno].sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001771 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001772 break;
1773 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001774# endif
1775# ifdef SYS_ipc_subcall
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001776 if (sysent[tcp->scno].sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001777 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001778 break;
1779 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001780# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001781 break;
1782 }
1783#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1784
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001785 internal_syscall(tcp);
1786
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001787 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001788 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1789 (tracing_paths && !pathtrace_match(tcp))) {
1790 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1791 return 0;
1792 }
1793
1794 tcp->flags &= ~TCB_FILTERED;
1795
1796 if (cflag == CFLAG_ONLY_STATS) {
1797 res = 0;
1798 goto ret;
1799 }
1800
1801 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001802 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001803 tprintf("syscall_%lu(", tcp->scno);
1804 else
1805 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001806 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001807 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1808 sysent[tcp->scno].sys_func != sys_exit))
1809 res = printargs(tcp);
1810 else
1811 res = (*sysent[tcp->scno].sys_func)(tcp);
1812
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001813 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001814 ret:
1815 tcp->flags |= TCB_INSYSCALL;
1816 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001817 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001818 gettimeofday(&tcp->etime, NULL);
1819 return res;
1820}
1821
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001822/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001823 * 1: ok, continue in trace_syscall_exiting().
1824 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001825 * ("????" etc) and bail out.
1826 */
1827static int
1828get_syscall_result(struct tcb *tcp)
1829{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001830#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001831 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1832 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001833#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001834# define SO_MASK 0x10000000
1835 {
1836 long flags;
1837 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1838 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001839 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001840 return -1;
1841 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001842 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001843 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001844#elif defined(AVR32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001845 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001846#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001847 if (upeek(tcp, PT_R0, &r0) < 0)
1848 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001849#elif defined(I386)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001850 /* already done by get_regs */
H.J. Lu35be5812012-04-16 13:00:01 +02001851#elif defined(X86_64) || defined(X32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001852 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001853#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001854# define IA64_PSR_IS ((long)1 << 34)
1855 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1856 ia32 = (psr & IA64_PSR_IS) != 0;
1857 if (upeek(tcp, PT_R8, &r8) < 0)
1858 return -1;
1859 if (upeek(tcp, PT_R10, &r10) < 0)
1860 return -1;
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001861#elif defined(AARCH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001862/* FIXME: uh, why do we do it on syscall *exit*? We did it on entry already... */
1863 /* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
1864 * else it's personality 0.
1865 */
1866 update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001867#elif defined(ARM)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001868 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001869#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001870 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1871 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001872#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001873 unsigned long long regs[38];
1874
1875 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1876 return -1;
1877 a3 = regs[REG_A3];
1878 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001879#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001880 if (upeek(tcp, REG_A3, &a3) < 0)
1881 return -1;
1882 if (upeek(tcp, REG_V0, &r2) < 0)
1883 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001884#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001885 if (upeek(tcp, REG_A3, &a3) < 0)
1886 return -1;
1887 if (upeek(tcp, REG_R0, &r0) < 0)
1888 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001889#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001890 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001891#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001892 if (upeek(tcp, PT_GR28, &r28) < 0)
1893 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001894#elif defined(SH)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001895 /* new syscall ABI returns result in R0 */
1896 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1897 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001898#elif defined(SH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001899 /* ABI defines result returned in r9 */
1900 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1901 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001902#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001903 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1904 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001905#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001906 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001907#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001908 if (upeek(tcp, 3 * 4, &r3) < 0)
1909 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001910#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001911 return 1;
1912}
1913
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001914/* Called at each syscall exit */
1915static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001916syscall_fixup_on_sysexit(struct tcb *tcp)
1917{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001918#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001919 if (syscall_mode != -ENOSYS)
1920 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001921 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001922 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1923 /*
1924 * Return from execve.
1925 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1926 * flag set for the post-execve SIGTRAP to see and reset.
1927 */
1928 gpr2 = 0;
1929 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001930#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001931}
1932
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001933/*
1934 * Check the syscall return value register value for whether it is
1935 * a negated errno code indicating an error, or a success return value.
1936 */
1937static inline int
1938is_negated_errno(unsigned long int val)
1939{
1940 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001941#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001942 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001943 val = (unsigned int) val;
1944 max = (unsigned int) max;
1945 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001946#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001947 return val > max;
1948}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001949
Denys Vlasenko907735a2012-03-21 00:23:16 +01001950/* Returns:
1951 * 1: ok, continue in trace_syscall_exiting().
1952 * -1: error, trace_syscall_exiting() should print error indicator
1953 * ("????" etc) and bail out.
1954 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001955static int
1956get_error(struct tcb *tcp)
1957{
1958 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001959 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001960 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001961 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1962 check_errno = 0;
1963 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001964#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001965 if (check_errno && is_negated_errno(gpr2)) {
1966 tcp->u_rval = -1;
1967 u_error = -gpr2;
1968 }
1969 else {
1970 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001971 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001972#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001973 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001974 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001975 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001976 }
1977 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001978 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001979 }
H.J. Lu35be5812012-04-16 13:00:01 +02001980#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001981 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001982 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001983 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001984 }
1985 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001986 tcp->u_rval = x86_64_regs.rax;
H.J. Lu35be5812012-04-16 13:00:01 +02001987# if defined(X32)
1988 tcp->u_lrval = x86_64_regs.rax;
1989# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001990 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001991#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001992 if (ia32) {
1993 int err;
1994
1995 err = (int)r8;
1996 if (check_errno && is_negated_errno(err)) {
1997 tcp->u_rval = -1;
1998 u_error = -err;
1999 }
2000 else {
2001 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002002 }
2003 } else {
2004 if (check_errno && r10) {
2005 tcp->u_rval = -1;
2006 u_error = r8;
2007 } else {
2008 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002009 }
2010 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002011#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002012 if (check_errno && a3) {
2013 tcp->u_rval = -1;
2014 u_error = r2;
2015 } else {
2016 tcp->u_rval = r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002017# if defined(LINUX_MIPSN32)
2018 tcp->u_lrval = r2;
2019# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002020 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002021#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002022 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002023 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002024 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002025 }
2026 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002027 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002028 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002029#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002030 if (check_errno && is_negated_errno(d0)) {
2031 tcp->u_rval = -1;
2032 u_error = -d0;
2033 }
2034 else {
2035 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002036 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002037#elif defined(ARM) || defined(AARCH64)
2038# if defined(AARCH64)
2039 if (tcp->currpers == 1) {
2040 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2041 tcp->u_rval = -1;
2042 u_error = -aarch64_regs.regs[0];
2043 }
2044 else {
2045 tcp->u_rval = aarch64_regs.regs[0];
2046 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002047 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002048 else
2049# endif /* AARCH64 */
2050 {
2051 if (check_errno && is_negated_errno(regs.ARM_r0)) {
2052 tcp->u_rval = -1;
2053 u_error = -regs.ARM_r0;
2054 }
2055 else {
2056 tcp->u_rval = regs.ARM_r0;
2057 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002058 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002059#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002060 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
2061 tcp->u_rval = -1;
2062 u_error = -regs.r12;
2063 }
2064 else {
2065 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002066 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002067#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002068 if (check_errno && is_negated_errno(r0)) {
2069 tcp->u_rval = -1;
2070 u_error = -r0;
2071 } else {
2072 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002073 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002074#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002075 if (check_errno && a3) {
2076 tcp->u_rval = -1;
2077 u_error = r0;
2078 }
2079 else {
2080 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002081 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002082#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002083 if (check_errno && regs.psr & PSR_C) {
2084 tcp->u_rval = -1;
2085 u_error = regs.u_regs[U_REG_O0];
2086 }
2087 else {
2088 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002089 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002090#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002091 if (check_errno && regs.tstate & 0x1100000000UL) {
2092 tcp->u_rval = -1;
2093 u_error = regs.u_regs[U_REG_O0];
2094 }
2095 else {
2096 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002097 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002098#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002099 if (check_errno && is_negated_errno(r28)) {
2100 tcp->u_rval = -1;
2101 u_error = -r28;
2102 }
2103 else {
2104 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002105 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002106#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002107 if (check_errno && is_negated_errno(r0)) {
2108 tcp->u_rval = -1;
2109 u_error = -r0;
2110 }
2111 else {
2112 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002113 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002114#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002115 if (check_errno && is_negated_errno(r9)) {
2116 tcp->u_rval = -1;
2117 u_error = -r9;
2118 }
2119 else {
2120 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002121 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002122#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002123 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
2124 tcp->u_rval = -1;
2125 u_error = -r10;
2126 }
2127 else {
2128 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002129 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002130#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002131 /*
2132 * The standard tile calling convention returns the value (or negative
2133 * errno) in r0, and zero (or positive errno) in r1.
2134 * Until at least kernel 3.8, however, the r1 value is not reflected
2135 * in ptregs at this point, so we use r0 here.
2136 */
2137 if (check_errno && is_negated_errno(tile_regs.regs[0])) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002138 tcp->u_rval = -1;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002139 u_error = -tile_regs.regs[0];
2140 } else {
2141 tcp->u_rval = tile_regs.regs[0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002142 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002143#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002144 if (check_errno && is_negated_errno(r3)) {
2145 tcp->u_rval = -1;
2146 u_error = -r3;
2147 }
2148 else {
2149 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002150 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002151#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002152 tcp->u_error = u_error;
2153 return 1;
2154}
2155
2156static void
2157dumpio(struct tcb *tcp)
2158{
2159 if (syserror(tcp))
2160 return;
2161 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
2162 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002163 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002164 return;
2165 if (sysent[tcp->scno].sys_func == printargs)
2166 return;
2167 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
2168 if (sysent[tcp->scno].sys_func == sys_read ||
2169 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002170 sysent[tcp->scno].sys_func == sys_recv ||
2171 sysent[tcp->scno].sys_func == sys_recvfrom)
2172 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
2173 else if (sysent[tcp->scno].sys_func == sys_readv)
2174 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2175 return;
2176 }
2177 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
2178 if (sysent[tcp->scno].sys_func == sys_write ||
2179 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002180 sysent[tcp->scno].sys_func == sys_send ||
2181 sysent[tcp->scno].sys_func == sys_sendto)
2182 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
2183 else if (sysent[tcp->scno].sys_func == sys_writev)
2184 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2185 return;
2186 }
2187}
2188
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002189static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002190trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002191{
2192 int sys_res;
2193 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002194 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002195 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002196
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002197 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002198 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002199 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002200
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002201#if SUPPORTED_PERSONALITIES > 1
2202 update_personality(tcp, tcp->currpers);
2203#endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002204 res = (get_regs_error ? -1 : get_syscall_result(tcp));
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002205 if (res == 1) {
2206 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01002207 res = get_error(tcp); /* returns 1 or -1 */
2208 if (res == 1) {
2209 internal_syscall(tcp);
2210 if (filtered(tcp)) {
2211 goto ret;
2212 }
2213 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002214 }
2215
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002216 if (cflag) {
2217 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002218 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002219 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002220 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002221 }
2222 }
2223
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002224 /* If not in -ff mode, and printing_tcp != tcp,
2225 * then the log currently does not end with output
2226 * of _our syscall entry_, but with something else.
2227 * We need to say which syscall's return is this.
2228 *
2229 * Forced reprinting via TCB_REPRINT is used only by
2230 * "strace -ff -oLOG test/threaded_execve" corner case.
2231 * It's the only case when -ff mode needs reprinting.
2232 */
2233 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2234 tcp->flags &= ~TCB_REPRINT;
2235 printleader(tcp);
2236 if (!SCNO_IN_RANGE(tcp->scno))
2237 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2238 else
2239 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2240 }
2241 printing_tcp = tcp;
2242
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002243 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002244 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002245 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002246 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002247 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002248 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002249 tcp->flags &= ~TCB_INSYSCALL;
2250 return res;
2251 }
2252
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002253 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002254 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002255 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002256 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002257 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002258 /* FIXME: not_failing_only (IOW, option -z) is broken:
2259 * failure of syscall is known only after syscall return.
2260 * Thus we end up with something like this on, say, ENOENT:
2261 * open("doesnt_exist", O_RDONLY <unfinished ...>
2262 * {next syscall decode}
2263 * whereas the intended result is that open(...) line
2264 * is not shown at all.
2265 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002266 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002267 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002268 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2269 }
2270
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002271 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002272 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002273 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002274 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002275 qual_flags[tcp->scno] & QUAL_RAW) {
2276 if (u_error)
2277 tprintf("= -1 (errno %ld)", u_error);
2278 else
2279 tprintf("= %#lx", tcp->u_rval);
2280 }
2281 else if (!(sys_res & RVAL_NONE) && u_error) {
2282 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002283 /* Blocked signals do not interrupt any syscalls.
2284 * In this case syscalls don't return ERESTARTfoo codes.
2285 *
2286 * Deadly signals set to SIG_DFL interrupt syscalls
2287 * and kill the process regardless of which of the codes below
2288 * is returned by the interrupted syscall.
2289 * In some cases, kernel forces a kernel-generated deadly
2290 * signal to be unblocked and set to SIG_DFL (and thus cause
2291 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2292 * or SIGILL. (The alternative is to leave process spinning
2293 * forever on the faulty instruction - not useful).
2294 *
2295 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2296 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2297 * but kernel will always restart them.
2298 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002299 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002300 /* Most common type of signal-interrupted syscall exit code.
2301 * The system call will be restarted with the same arguments
2302 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2303 */
2304 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002305 break;
2306 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002307 /* Rare. For example, fork() returns this if interrupted.
2308 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2309 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002310 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002311 break;
2312 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002313 /* pause(), rt_sigsuspend() etc use this code.
2314 * SA_RESTART is ignored (assumed not set):
2315 * syscall won't restart (will return EINTR instead)
2316 * even after signal with SA_RESTART set.
2317 * However, after SIG_IGN or SIG_DFL signal it will.
2318 */
2319 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002320 break;
2321 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002322 /* Syscalls like nanosleep(), poll() which can't be
2323 * restarted with their original arguments use this
2324 * code. Kernel will execute restart_syscall() instead,
2325 * which changes arguments before restarting syscall.
2326 * SA_RESTART is ignored (assumed not set) similarly
2327 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2328 * since restart data is saved in "restart block"
2329 * in task struct, and if signal handler uses a syscall
2330 * which in turn saves another such restart block,
2331 * old data is lost and restart becomes impossible)
2332 */
2333 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002334 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002335 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002336 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002337 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002338 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002339 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002340 strerror(u_error));
2341 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002342 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002343 strerror(u_error));
2344 break;
2345 }
2346 if ((sys_res & RVAL_STR) && tcp->auxstr)
2347 tprintf(" (%s)", tcp->auxstr);
2348 }
2349 else {
2350 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002351 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002352 else {
2353 switch (sys_res & RVAL_MASK) {
2354 case RVAL_HEX:
2355 tprintf("= %#lx", tcp->u_rval);
2356 break;
2357 case RVAL_OCTAL:
2358 tprintf("= %#lo", tcp->u_rval);
2359 break;
2360 case RVAL_UDECIMAL:
2361 tprintf("= %lu", tcp->u_rval);
2362 break;
2363 case RVAL_DECIMAL:
2364 tprintf("= %ld", tcp->u_rval);
2365 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002366#if defined(LINUX_MIPSN32) || defined(X32)
2367 /*
2368 case RVAL_LHEX:
2369 tprintf("= %#llx", tcp->u_lrval);
2370 break;
2371 case RVAL_LOCTAL:
2372 tprintf("= %#llo", tcp->u_lrval);
2373 break;
2374 */
2375 case RVAL_LUDECIMAL:
2376 tprintf("= %llu", tcp->u_lrval);
2377 break;
2378 /*
2379 case RVAL_LDECIMAL:
2380 tprintf("= %lld", tcp->u_lrval);
2381 break;
2382 */
2383#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002384 default:
2385 fprintf(stderr,
2386 "invalid rval format\n");
2387 break;
2388 }
2389 }
2390 if ((sys_res & RVAL_STR) && tcp->auxstr)
2391 tprintf(" (%s)", tcp->auxstr);
2392 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002393 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002394 tv_sub(&tv, &tv, &tcp->etime);
2395 tprintf(" <%ld.%06ld>",
2396 (long) tv.tv_sec, (long) tv.tv_usec);
2397 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002398 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002399 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002400 line_ended();
2401
Denys Vlasenko3b738812011-08-22 02:06:35 +02002402 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002403 tcp->flags &= ~TCB_INSYSCALL;
2404 return 0;
2405}
2406
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002407int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002408trace_syscall(struct tcb *tcp)
2409{
2410 return exiting(tcp) ?
2411 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2412}