blob: 0eb1fd1c628d0e3210d4713478e67b0191ee1423 [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
Dmitry V. Levinddba73e2013-02-05 19:01:58 +0000741 tprintf("[%016lx] ", psw);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100742# endif
743#elif defined(X86_64) || defined(X32)
Dmitry V. Levinddba73e2013-02-05 19:01:58 +0000744 tprintf("[%016lx] ", (unsigned long) x86_64_regs.rip);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100745#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
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500848 tprintf("[%016lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100849# else
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500850 tprintf("[%08lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100851# 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)
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500889 get_regs_error = ptrace(PTRACE_GETREGS, 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 Vlasenko8d4ca0c2013-02-06 13:18:42 +01001485syscall_fixup_for_fork_exec(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 Vlasenko8d4ca0c2013-02-06 13:18:42 +01001785 if (need_fork_exec_workarounds)
1786 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001787
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001788 if ((SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001789 !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1790 (tracing_paths && !pathtrace_match(tcp))) {
1791 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1792 return 0;
1793 }
1794
1795 tcp->flags &= ~TCB_FILTERED;
1796
1797 if (cflag == CFLAG_ONLY_STATS) {
1798 res = 0;
1799 goto ret;
1800 }
1801
1802 printleader(tcp);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001803 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001804 tprintf("syscall_%lu(", tcp->scno);
1805 else
1806 tprintf("%s(", sysent[tcp->scno].sys_name);
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001807 if (!SCNO_IN_RANGE(tcp->scno) ||
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001808 ((qual_flags[tcp->scno] & QUAL_RAW) &&
1809 sysent[tcp->scno].sys_func != sys_exit))
1810 res = printargs(tcp);
1811 else
1812 res = (*sysent[tcp->scno].sys_func)(tcp);
1813
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00001814 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001815 ret:
1816 tcp->flags |= TCB_INSYSCALL;
1817 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001818 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001819 gettimeofday(&tcp->etime, NULL);
1820 return res;
1821}
1822
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001823/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001824 * 1: ok, continue in trace_syscall_exiting().
1825 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001826 * ("????" etc) and bail out.
1827 */
1828static int
1829get_syscall_result(struct tcb *tcp)
1830{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001831#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001832 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1833 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001834#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001835# define SO_MASK 0x10000000
1836 {
1837 long flags;
1838 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1839 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001840 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001841 return -1;
1842 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01001843 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001844 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001845#elif defined(AVR32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001846 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001847#elif defined(BFIN)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001848 if (upeek(tcp, PT_R0, &r0) < 0)
1849 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001850#elif defined(I386)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001851 /* already done by get_regs */
H.J. Lu35be5812012-04-16 13:00:01 +02001852#elif defined(X86_64) || defined(X32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001853 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001854#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001855# define IA64_PSR_IS ((long)1 << 34)
1856 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1857 ia32 = (psr & IA64_PSR_IS) != 0;
1858 if (upeek(tcp, PT_R8, &r8) < 0)
1859 return -1;
1860 if (upeek(tcp, PT_R10, &r10) < 0)
1861 return -1;
Steve McIntyred8d3bd32012-10-24 17:58:16 +01001862#elif defined(AARCH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001863/* FIXME: uh, why do we do it on syscall *exit*? We did it on entry already... */
1864 /* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
1865 * else it's personality 0.
1866 */
1867 update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001868#elif defined(ARM)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001869 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001870#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001871 if (upeek(tcp, 4*PT_D0, &d0) < 0)
1872 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001873#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001874 unsigned long long regs[38];
1875
1876 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1877 return -1;
1878 a3 = regs[REG_A3];
1879 r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001880#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001881 if (upeek(tcp, REG_A3, &a3) < 0)
1882 return -1;
1883 if (upeek(tcp, REG_V0, &r2) < 0)
1884 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001885#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001886 if (upeek(tcp, REG_A3, &a3) < 0)
1887 return -1;
1888 if (upeek(tcp, REG_R0, &r0) < 0)
1889 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001890#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001891 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001892#elif defined(HPPA)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001893 if (upeek(tcp, PT_GR28, &r28) < 0)
1894 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001895#elif defined(SH)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001896 /* new syscall ABI returns result in R0 */
1897 if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1898 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001899#elif defined(SH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001900 /* ABI defines result returned in r9 */
1901 if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1902 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001903#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001904 if (upeek(tcp, 4*PT_R10, &r10) < 0)
1905 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001906#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001907 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001908#elif defined(MICROBLAZE)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001909 if (upeek(tcp, 3 * 4, &r3) < 0)
1910 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001911#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001912 return 1;
1913}
1914
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001915/* Called at each syscall exit */
1916static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001917syscall_fixup_on_sysexit(struct tcb *tcp)
1918{
Denys Vlasenko523635f2012-02-25 02:44:25 +01001919#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001920 if (syscall_mode != -ENOSYS)
1921 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001922 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001923 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1924 /*
1925 * Return from execve.
1926 * Fake a return value of zero. We leave the TCB_WAITEXECVE
1927 * flag set for the post-execve SIGTRAP to see and reset.
1928 */
1929 gpr2 = 0;
1930 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001931#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001932}
1933
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001934/*
1935 * Check the syscall return value register value for whether it is
1936 * a negated errno code indicating an error, or a success return value.
1937 */
1938static inline int
1939is_negated_errno(unsigned long int val)
1940{
1941 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001942#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001943 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001944 val = (unsigned int) val;
1945 max = (unsigned int) max;
1946 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001947#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001948 return val > max;
1949}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001950
Denys Vlasenko907735a2012-03-21 00:23:16 +01001951/* Returns:
1952 * 1: ok, continue in trace_syscall_exiting().
1953 * -1: error, trace_syscall_exiting() should print error indicator
1954 * ("????" etc) and bail out.
1955 */
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001956static int
1957get_error(struct tcb *tcp)
1958{
1959 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001960 int check_errno = 1;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02001961 if (SCNO_IN_RANGE(tcp->scno) &&
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001962 sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1963 check_errno = 0;
1964 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001965#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001966 if (check_errno && is_negated_errno(gpr2)) {
1967 tcp->u_rval = -1;
1968 u_error = -gpr2;
1969 }
1970 else {
1971 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001972 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001973#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001974 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001975 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001976 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001977 }
1978 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001979 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001980 }
H.J. Lu35be5812012-04-16 13:00:01 +02001981#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001982 if (check_errno && is_negated_errno(x86_64_regs.rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001983 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001984 u_error = -x86_64_regs.rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001985 }
1986 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001987 tcp->u_rval = x86_64_regs.rax;
H.J. Lu35be5812012-04-16 13:00:01 +02001988# if defined(X32)
1989 tcp->u_lrval = x86_64_regs.rax;
1990# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001991 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001992#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001993 if (ia32) {
1994 int err;
1995
1996 err = (int)r8;
1997 if (check_errno && is_negated_errno(err)) {
1998 tcp->u_rval = -1;
1999 u_error = -err;
2000 }
2001 else {
2002 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002003 }
2004 } else {
2005 if (check_errno && r10) {
2006 tcp->u_rval = -1;
2007 u_error = r8;
2008 } else {
2009 tcp->u_rval = r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002010 }
2011 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002012#elif defined(MIPS)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002013 if (check_errno && a3) {
2014 tcp->u_rval = -1;
2015 u_error = r2;
2016 } else {
2017 tcp->u_rval = r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002018# if defined(LINUX_MIPSN32)
2019 tcp->u_lrval = r2;
2020# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002021 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002022#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002023 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002024 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002025 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002026 }
2027 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002028 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002029 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002030#elif defined(M68K)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002031 if (check_errno && is_negated_errno(d0)) {
2032 tcp->u_rval = -1;
2033 u_error = -d0;
2034 }
2035 else {
2036 tcp->u_rval = d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002037 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002038#elif defined(ARM) || defined(AARCH64)
2039# if defined(AARCH64)
2040 if (tcp->currpers == 1) {
2041 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2042 tcp->u_rval = -1;
2043 u_error = -aarch64_regs.regs[0];
2044 }
2045 else {
2046 tcp->u_rval = aarch64_regs.regs[0];
2047 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002048 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002049 else
2050# endif /* AARCH64 */
2051 {
2052 if (check_errno && is_negated_errno(regs.ARM_r0)) {
2053 tcp->u_rval = -1;
2054 u_error = -regs.ARM_r0;
2055 }
2056 else {
2057 tcp->u_rval = regs.ARM_r0;
2058 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002059 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002060#elif defined(AVR32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002061 if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
2062 tcp->u_rval = -1;
2063 u_error = -regs.r12;
2064 }
2065 else {
2066 tcp->u_rval = regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002067 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002068#elif defined(BFIN)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002069 if (check_errno && is_negated_errno(r0)) {
2070 tcp->u_rval = -1;
2071 u_error = -r0;
2072 } else {
2073 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002074 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002075#elif defined(ALPHA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002076 if (check_errno && a3) {
2077 tcp->u_rval = -1;
2078 u_error = r0;
2079 }
2080 else {
2081 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002082 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002083#elif defined(SPARC)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002084 if (check_errno && regs.psr & PSR_C) {
2085 tcp->u_rval = -1;
2086 u_error = regs.u_regs[U_REG_O0];
2087 }
2088 else {
2089 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002090 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002091#elif defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002092 if (check_errno && regs.tstate & 0x1100000000UL) {
2093 tcp->u_rval = -1;
2094 u_error = regs.u_regs[U_REG_O0];
2095 }
2096 else {
2097 tcp->u_rval = regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002098 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002099#elif defined(HPPA)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002100 if (check_errno && is_negated_errno(r28)) {
2101 tcp->u_rval = -1;
2102 u_error = -r28;
2103 }
2104 else {
2105 tcp->u_rval = r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002106 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002107#elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002108 if (check_errno && is_negated_errno(r0)) {
2109 tcp->u_rval = -1;
2110 u_error = -r0;
2111 }
2112 else {
2113 tcp->u_rval = r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002114 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002115#elif defined(SH64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002116 if (check_errno && is_negated_errno(r9)) {
2117 tcp->u_rval = -1;
2118 u_error = -r9;
2119 }
2120 else {
2121 tcp->u_rval = r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002122 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002123#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002124 if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
2125 tcp->u_rval = -1;
2126 u_error = -r10;
2127 }
2128 else {
2129 tcp->u_rval = r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002130 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002131#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002132 /*
2133 * The standard tile calling convention returns the value (or negative
2134 * errno) in r0, and zero (or positive errno) in r1.
2135 * Until at least kernel 3.8, however, the r1 value is not reflected
2136 * in ptregs at this point, so we use r0 here.
2137 */
2138 if (check_errno && is_negated_errno(tile_regs.regs[0])) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002139 tcp->u_rval = -1;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002140 u_error = -tile_regs.regs[0];
2141 } else {
2142 tcp->u_rval = tile_regs.regs[0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002143 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002144#elif defined(MICROBLAZE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002145 if (check_errno && is_negated_errno(r3)) {
2146 tcp->u_rval = -1;
2147 u_error = -r3;
2148 }
2149 else {
2150 tcp->u_rval = r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002151 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002152#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002153 tcp->u_error = u_error;
2154 return 1;
2155}
2156
2157static void
2158dumpio(struct tcb *tcp)
2159{
2160 if (syserror(tcp))
2161 return;
2162 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
2163 return;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002164 if (!SCNO_IN_RANGE(tcp->scno))
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002165 return;
2166 if (sysent[tcp->scno].sys_func == printargs)
2167 return;
2168 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
2169 if (sysent[tcp->scno].sys_func == sys_read ||
2170 sysent[tcp->scno].sys_func == sys_pread ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002171 sysent[tcp->scno].sys_func == sys_recv ||
2172 sysent[tcp->scno].sys_func == sys_recvfrom)
2173 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
2174 else if (sysent[tcp->scno].sys_func == sys_readv)
2175 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2176 return;
2177 }
2178 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
2179 if (sysent[tcp->scno].sys_func == sys_write ||
2180 sysent[tcp->scno].sys_func == sys_pwrite ||
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002181 sysent[tcp->scno].sys_func == sys_send ||
2182 sysent[tcp->scno].sys_func == sys_sendto)
2183 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
2184 else if (sysent[tcp->scno].sys_func == sys_writev)
2185 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2186 return;
2187 }
2188}
2189
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002190static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002191trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002192{
2193 int sys_res;
2194 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002195 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002196 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002197
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002198 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002199 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002200 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002201
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002202#if SUPPORTED_PERSONALITIES > 1
2203 update_personality(tcp, tcp->currpers);
2204#endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002205 res = (get_regs_error ? -1 : get_syscall_result(tcp));
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002206 if (res == 1) {
2207 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenko907735a2012-03-21 00:23:16 +01002208 res = get_error(tcp); /* returns 1 or -1 */
2209 if (res == 1) {
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01002210 if (need_fork_exec_workarounds)
2211 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01002212 if (filtered(tcp)) {
2213 goto ret;
2214 }
2215 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00002216 }
2217
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002218 if (cflag) {
2219 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002220 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002221 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002222 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002223 }
2224 }
2225
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002226 /* If not in -ff mode, and printing_tcp != tcp,
2227 * then the log currently does not end with output
2228 * of _our syscall entry_, but with something else.
2229 * We need to say which syscall's return is this.
2230 *
2231 * Forced reprinting via TCB_REPRINT is used only by
2232 * "strace -ff -oLOG test/threaded_execve" corner case.
2233 * It's the only case when -ff mode needs reprinting.
2234 */
2235 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2236 tcp->flags &= ~TCB_REPRINT;
2237 printleader(tcp);
2238 if (!SCNO_IN_RANGE(tcp->scno))
2239 tprintf("<... syscall_%lu resumed> ", tcp->scno);
2240 else
2241 tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2242 }
2243 printing_tcp = tcp;
2244
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002245 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002246 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002247 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002248 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002249 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002250 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002251 tcp->flags &= ~TCB_INSYSCALL;
2252 return res;
2253 }
2254
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002255 sys_res = 0;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002256 if (!SCNO_IN_RANGE(tcp->scno)
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002257 || (qual_flags[tcp->scno] & QUAL_RAW)) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002258 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002259 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002260 /* FIXME: not_failing_only (IOW, option -z) is broken:
2261 * failure of syscall is known only after syscall return.
2262 * Thus we end up with something like this on, say, ENOENT:
2263 * open("doesnt_exist", O_RDONLY <unfinished ...>
2264 * {next syscall decode}
2265 * whereas the intended result is that open(...) line
2266 * is not shown at all.
2267 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002268 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002269 goto ret; /* ignore failed syscalls */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002270 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2271 }
2272
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002273 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002274 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002275 u_error = tcp->u_error;
Denys Vlasenkocb6f0562011-08-25 01:13:43 +02002276 if (!SCNO_IN_RANGE(tcp->scno) ||
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002277 qual_flags[tcp->scno] & QUAL_RAW) {
2278 if (u_error)
2279 tprintf("= -1 (errno %ld)", u_error);
2280 else
2281 tprintf("= %#lx", tcp->u_rval);
2282 }
2283 else if (!(sys_res & RVAL_NONE) && u_error) {
2284 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002285 /* Blocked signals do not interrupt any syscalls.
2286 * In this case syscalls don't return ERESTARTfoo codes.
2287 *
2288 * Deadly signals set to SIG_DFL interrupt syscalls
2289 * and kill the process regardless of which of the codes below
2290 * is returned by the interrupted syscall.
2291 * In some cases, kernel forces a kernel-generated deadly
2292 * signal to be unblocked and set to SIG_DFL (and thus cause
2293 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2294 * or SIGILL. (The alternative is to leave process spinning
2295 * forever on the faulty instruction - not useful).
2296 *
2297 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2298 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2299 * but kernel will always restart them.
2300 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002301 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002302 /* Most common type of signal-interrupted syscall exit code.
2303 * The system call will be restarted with the same arguments
2304 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2305 */
2306 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002307 break;
2308 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002309 /* Rare. For example, fork() returns this if interrupted.
2310 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2311 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002312 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002313 break;
2314 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002315 /* pause(), rt_sigsuspend() etc use this code.
2316 * SA_RESTART is ignored (assumed not set):
2317 * syscall won't restart (will return EINTR instead)
2318 * even after signal with SA_RESTART set.
2319 * However, after SIG_IGN or SIG_DFL signal it will.
2320 */
2321 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002322 break;
2323 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002324 /* Syscalls like nanosleep(), poll() which can't be
2325 * restarted with their original arguments use this
2326 * code. Kernel will execute restart_syscall() instead,
2327 * which changes arguments before restarting syscall.
2328 * SA_RESTART is ignored (assumed not set) similarly
2329 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2330 * since restart data is saved in "restart block"
2331 * in task struct, and if signal handler uses a syscall
2332 * which in turn saves another such restart block,
2333 * old data is lost and restart becomes impossible)
2334 */
2335 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002336 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002337 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002338 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002339 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002340 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002341 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002342 strerror(u_error));
2343 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002344 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002345 strerror(u_error));
2346 break;
2347 }
2348 if ((sys_res & RVAL_STR) && tcp->auxstr)
2349 tprintf(" (%s)", tcp->auxstr);
2350 }
2351 else {
2352 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002353 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002354 else {
2355 switch (sys_res & RVAL_MASK) {
2356 case RVAL_HEX:
2357 tprintf("= %#lx", tcp->u_rval);
2358 break;
2359 case RVAL_OCTAL:
2360 tprintf("= %#lo", tcp->u_rval);
2361 break;
2362 case RVAL_UDECIMAL:
2363 tprintf("= %lu", tcp->u_rval);
2364 break;
2365 case RVAL_DECIMAL:
2366 tprintf("= %ld", tcp->u_rval);
2367 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002368#if defined(LINUX_MIPSN32) || defined(X32)
2369 /*
2370 case RVAL_LHEX:
2371 tprintf("= %#llx", tcp->u_lrval);
2372 break;
2373 case RVAL_LOCTAL:
2374 tprintf("= %#llo", tcp->u_lrval);
2375 break;
2376 */
2377 case RVAL_LUDECIMAL:
2378 tprintf("= %llu", tcp->u_lrval);
2379 break;
2380 /*
2381 case RVAL_LDECIMAL:
2382 tprintf("= %lld", tcp->u_lrval);
2383 break;
2384 */
2385#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002386 default:
2387 fprintf(stderr,
2388 "invalid rval format\n");
2389 break;
2390 }
2391 }
2392 if ((sys_res & RVAL_STR) && tcp->auxstr)
2393 tprintf(" (%s)", tcp->auxstr);
2394 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002395 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002396 tv_sub(&tv, &tv, &tcp->etime);
2397 tprintf(" <%ld.%06ld>",
2398 (long) tv.tv_sec, (long) tv.tv_usec);
2399 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002400 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002401 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002402 line_ended();
2403
Denys Vlasenko3b738812011-08-22 02:06:35 +02002404 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002405 tcp->flags &= ~TCB_INSYSCALL;
2406 return 0;
2407}
2408
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002409int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002410trace_syscall(struct tcb *tcp)
2411{
2412 return exiting(tcp) ?
2413 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2414}