blob: ffa0cd4aa9436d17ed21f028490f8bb69d0e1099 [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Linux for s390 port by D.J. Barrow
8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000032 */
33
34#include "defs.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000035#include <sys/user.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000036#include <sys/param.h>
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000037
Wichert Akkerman15dea971999-10-06 13:06:34 +000038#ifdef HAVE_SYS_REG_H
Denys Vlasenko523635f2012-02-25 02:44:25 +010039# include <sys/reg.h>
40# ifndef PTRACE_PEEKUSR
41# define PTRACE_PEEKUSR PTRACE_PEEKUSER
42# endif
Wichert Akkermanfaf72222000-02-19 23:59:03 +000043#elif defined(HAVE_LINUX_PTRACE_H)
Denys Vlasenko523635f2012-02-25 02:44:25 +010044# undef PTRACE_SYSCALL
Roland McGrathce9f0742004-03-01 21:29:22 +000045# ifdef HAVE_STRUCT_IA64_FPREG
46# define ia64_fpreg XXX_ia64_fpreg
47# endif
48# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
49# define pt_all_user_regs XXX_pt_all_user_regs
50# endif
Denys Vlasenko523635f2012-02-25 02:44:25 +010051# include <linux/ptrace.h>
Roland McGrathce9f0742004-03-01 21:29:22 +000052# undef ia64_fpreg
53# undef pt_all_user_regs
Wichert Akkerman15dea971999-10-06 13:06:34 +000054#endif
55
Denys Vlasenko84703742012-02-25 02:38:52 +010056#if defined(SPARC64)
Roland McGrath6d1a65c2004-07-12 07:44:08 +000057# undef PTRACE_GETREGS
58# define PTRACE_GETREGS PTRACE_GETREGS64
59# undef PTRACE_SETREGS
60# define PTRACE_SETREGS PTRACE_SETREGS64
Denys Vlasenko84703742012-02-25 02:38:52 +010061#endif
Roland McGrath6d1a65c2004-07-12 07:44:08 +000062
Denys Vlasenko84703742012-02-25 02:38:52 +010063#if defined(IA64)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +000064# include <asm/ptrace_offsets.h>
65# include <asm/rse.h>
66#endif
67
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +010068#if defined(X86_64) || defined(X32)
69# include <linux/ptrace.h>
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +010070# include <sys/uio.h>
71# include <elf.h>
72#endif
73
Steve McIntyred8d3bd32012-10-24 17:58:16 +010074#if defined(AARCH64)
75# include <asm/ptrace.h>
76# include <sys/uio.h>
77# include <elf.h>
78#endif
79
Christian Svensson492f81f2013-02-14 13:26:27 +010080#if defined(OR1K)
81# include <sys/uio.h>
82# include <elf.h>
83#endif
84
James Hogan5f999a82013-02-22 14:44:10 +000085#if defined(METAG)
86# include <sys/uio.h>
87# include <elf.h>
88#endif
89
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000090#ifndef ERESTARTSYS
Denys Vlasenko523635f2012-02-25 02:44:25 +010091# define ERESTARTSYS 512
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000092#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010093#ifndef ERESTARTNOINTR
Denys Vlasenko523635f2012-02-25 02:44:25 +010094# define ERESTARTNOINTR 513
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000095#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010096#ifndef ERESTARTNOHAND
97# define ERESTARTNOHAND 514 /* restart if no handler */
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000098#endif
Denys Vlasenko3da96932012-03-17 03:17:15 +010099#ifndef ERESTART_RESTARTBLOCK
Denys Vlasenko523635f2012-02-25 02:44:25 +0100100# define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
Roland McGrath9c555e72003-07-09 09:47:59 +0000101#endif
Denys Vlasenko523635f2012-02-25 02:44:25 +0100102
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000103#ifndef NSIG
Denys Vlasenko523635f2012-02-25 02:44:25 +0100104# warning: NSIG is not defined, using 32
105# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000106#endif
107#ifdef ARM
Denys Vlasenko041b3ee2011-08-18 12:48:56 +0200108/* Ugh. Is this really correct? ARM has no RT signals?! */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100109# undef NSIG
110# define NSIG 32
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000111#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000112
113#include "syscall.h"
114
115/* Define these shorthand notations to simplify the syscallent files. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000116#define TD TRACE_DESC
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000117#define TF TRACE_FILE
118#define TI TRACE_IPC
119#define TN TRACE_NETWORK
120#define TP TRACE_PROCESS
121#define TS TRACE_SIGNAL
Namhyung Kim96792962012-10-24 11:41:57 +0900122#define TM TRACE_MEMORY
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000123#define NF SYSCALL_NEVER_FAILS
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200124#define MA MAX_ARGS
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000125
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100126const struct_sysent sysent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000127#include "syscallent.h"
128};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000129
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100130#if SUPPORTED_PERSONALITIES > 1
131static const struct_sysent sysent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100132# include "syscallent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000133};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200134#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000135
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100136#if SUPPORTED_PERSONALITIES > 2
137static const struct_sysent sysent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100138# include "syscallent2.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000139};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200140#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000141
142/* Now undef them since short defines cause wicked namespace pollution. */
Roland McGrath2fe7b132005-07-05 03:25:35 +0000143#undef TD
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000144#undef TF
145#undef TI
146#undef TN
147#undef TP
148#undef TS
Namhyung Kim96792962012-10-24 11:41:57 +0900149#undef TM
Dmitry V. Levin50a218d2011-01-18 17:36:20 +0000150#undef NF
Denys Vlasenkoac1ce772011-08-23 13:24:17 +0200151#undef MA
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000152
Denys Vlasenko39fca622011-08-20 02:12:33 +0200153/*
154 * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
155 * program `ioctlsort', such that the list is sorted by the `code' field.
156 * This has the side-effect of resolving the _IO.. macros into
157 * plain integers, eliminating the need to include here everything
158 * in "/usr/include".
159 */
160
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100161const char *const errnoent0[] = {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000162#include "errnoent.h"
163};
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100164const char *const signalent0[] = {
Denys Vlasenko39fca622011-08-20 02:12:33 +0200165#include "signalent.h"
166};
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100167const struct_ioctlent ioctlent0[] = {
Denys Vlasenko39fca622011-08-20 02:12:33 +0200168#include "ioctlent.h"
169};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000170
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100171#if SUPPORTED_PERSONALITIES > 1
Roland McGrathee36ce12004-09-04 03:53:10 +0000172static const char *const errnoent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100173# include "errnoent1.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000174};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200175static const char *const signalent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100176# include "signalent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200177};
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100178static const struct_ioctlent ioctlent1[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100179# include "ioctlent1.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200180};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200181#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000182
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100183#if SUPPORTED_PERSONALITIES > 2
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};
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100190static const struct_ioctlent ioctlent2[] = {
Denys Vlasenko523635f2012-02-25 02:44:25 +0100191# include "ioctlent2.h"
Denys Vlasenko39fca622011-08-20 02:12:33 +0200192};
Denys Vlasenko39fca622011-08-20 02:12:33 +0200193#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000194
Dmitry V. Levine6f55242013-02-26 22:02:30 +0000195enum {
196 nsyscalls0 = ARRAY_SIZE(sysent0)
197#if SUPPORTED_PERSONALITIES > 1
198 , nsyscalls1 = ARRAY_SIZE(sysent1)
199# if SUPPORTED_PERSONALITIES > 2
200 , nsyscalls2 = ARRAY_SIZE(sysent2)
201# endif
202#endif
203};
204
205enum {
206 nerrnos0 = ARRAY_SIZE(errnoent0)
207#if SUPPORTED_PERSONALITIES > 1
208 , nerrnos1 = ARRAY_SIZE(errnoent1)
209# if SUPPORTED_PERSONALITIES > 2
210 , nerrnos2 = ARRAY_SIZE(errnoent2)
211# endif
212#endif
213};
214
215enum {
216 nsignals0 = ARRAY_SIZE(signalent0)
217#if SUPPORTED_PERSONALITIES > 1
218 , nsignals1 = ARRAY_SIZE(signalent1)
219# if SUPPORTED_PERSONALITIES > 2
220 , nsignals2 = ARRAY_SIZE(signalent2)
221# endif
222#endif
223};
224
225enum {
226 nioctlents0 = ARRAY_SIZE(ioctlent0)
227#if SUPPORTED_PERSONALITIES > 1
228 , nioctlents1 = ARRAY_SIZE(ioctlent1)
229# if SUPPORTED_PERSONALITIES > 2
230 , nioctlents2 = ARRAY_SIZE(ioctlent2)
231# endif
232#endif
233};
234
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100235#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100236const struct_sysent *sysent = sysent0;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100237const char *const *errnoent = errnoent0;
238const char *const *signalent = signalent0;
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100239const struct_ioctlent *ioctlent = ioctlent0;
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100240#endif
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100241unsigned nsyscalls = nsyscalls0;
242unsigned nerrnos = nerrnos0;
243unsigned nsignals = nsignals0;
244unsigned nioctlents = nioctlents0;
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100245
246unsigned num_quals;
247qualbits_t *qual_vec[SUPPORTED_PERSONALITIES];
248
249static const unsigned nsyscall_vec[SUPPORTED_PERSONALITIES] = {
250 nsyscalls0,
251#if SUPPORTED_PERSONALITIES > 1
252 nsyscalls1,
253#endif
254#if SUPPORTED_PERSONALITIES > 2
255 nsyscalls2,
256#endif
257};
258static const struct_sysent *const sysent_vec[SUPPORTED_PERSONALITIES] = {
259 sysent0,
260#if SUPPORTED_PERSONALITIES > 1
261 sysent1,
262#endif
263#if SUPPORTED_PERSONALITIES > 2
264 sysent2,
265#endif
266};
267
268enum {
269 MAX_NSYSCALLS1 = (nsyscalls0
270#if SUPPORTED_PERSONALITIES > 1
271 > nsyscalls1 ? nsyscalls0 : nsyscalls1
272#endif
273 ),
274 MAX_NSYSCALLS2 = (MAX_NSYSCALLS1
275#if SUPPORTED_PERSONALITIES > 2
276 > nsyscalls2 ? MAX_NSYSCALLS1 : nsyscalls2
277#endif
278 ),
279 MAX_NSYSCALLS = MAX_NSYSCALLS2,
280 /* We are ready for arches with up to 255 signals,
281 * even though the largest known signo is on MIPS and it is 128.
282 * The number of existing syscalls on all arches is
283 * larger that 255 anyway, so it is just a pedantic matter.
284 */
285 MIN_QUALS = MAX_NSYSCALLS > 255 ? MAX_NSYSCALLS : 255
286};
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000287
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100288#if SUPPORTED_PERSONALITIES > 1
Denys Vlasenkoae8643e2013-02-15 14:55:14 +0100289unsigned current_personality;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000290
Denys Vlasenkoae8643e2013-02-15 14:55:14 +0100291# ifndef current_wordsize
292unsigned current_wordsize;
293static const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000294 PERSONALITY0_WORDSIZE,
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000295 PERSONALITY1_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100296# if SUPPORTED_PERSONALITIES > 2
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000297 PERSONALITY2_WORDSIZE,
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100298# endif
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200299};
Denys Vlasenkoae8643e2013-02-15 14:55:14 +0100300# endif
Roland McGrath4b2dcca2006-01-12 10:18:53 +0000301
Denys Vlasenko5c774b22011-08-20 01:50:09 +0200302void
Dmitry V. Levin3abe8b22006-12-20 22:37:21 +0000303set_personality(int personality)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000304{
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100305 nsyscalls = nsyscall_vec[personality];
306 sysent = sysent_vec[personality];
307
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000308 switch (personality) {
309 case 0:
310 errnoent = errnoent0;
311 nerrnos = nerrnos0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000312 ioctlent = ioctlent0;
313 nioctlents = nioctlents0;
314 signalent = signalent0;
315 nsignals = nsignals0;
316 break;
317
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000318 case 1:
319 errnoent = errnoent1;
320 nerrnos = nerrnos1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000321 ioctlent = ioctlent1;
322 nioctlents = nioctlents1;
323 signalent = signalent1;
324 nsignals = nsignals1;
325 break;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000326
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +0100327# if SUPPORTED_PERSONALITIES > 2
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000328 case 2:
329 errnoent = errnoent2;
330 nerrnos = nerrnos2;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000331 ioctlent = ioctlent2;
332 nioctlents = nioctlents2;
333 signalent = signalent2;
334 nsignals = nsignals2;
335 break;
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100336# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000337 }
338
339 current_personality = personality;
Denys Vlasenkoae8643e2013-02-15 14:55:14 +0100340# ifndef current_wordsize
341 current_wordsize = personality_wordsize[personality];
342# endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000343}
344
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000345static void
346update_personality(struct tcb *tcp, int personality)
347{
348 if (personality == current_personality)
349 return;
350 set_personality(personality);
351
352 if (personality == tcp->currpers)
353 return;
354 tcp->currpers = personality;
355
H.J. Lu35be5812012-04-16 13:00:01 +0200356# if defined(POWERPC64)
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000357 if (!qflag) {
358 static const char *const names[] = {"64 bit", "32 bit"};
359 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
360 tcp->pid, names[personality]);
361 }
H.J. Lu35be5812012-04-16 13:00:01 +0200362# elif defined(X86_64)
363 if (!qflag) {
364 static const char *const names[] = {"64 bit", "32 bit", "x32"};
365 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
366 tcp->pid, names[personality]);
367 }
H.J. Lu085e4282012-04-17 11:05:04 -0700368# elif defined(X32)
369 if (!qflag) {
370 static const char *const names[] = {"x32", "32 bit"};
371 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
372 tcp->pid, names[personality]);
373 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000374# elif defined(AARCH64)
375 if (!qflag) {
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100376 static const char *const names[] = {"32-bit", "AArch64"};
Steve McIntyre890a5ca2012-11-10 11:24:48 +0000377 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
378 tcp->pid, names[personality]);
379 }
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100380# elif defined(TILE)
381 if (!qflag) {
382 static const char *const names[] = {"64-bit", "32-bit"};
383 fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
384 tcp->pid, names[personality]);
385 }
Denys Vlasenko523635f2012-02-25 02:44:25 +0100386# endif
Dmitry V. Levina5a839a2011-12-23 00:50:49 +0000387}
388#endif
Roland McGrathe10e62a2004-09-04 04:20:43 +0000389
Denys Vlasenkoc1540fe2013-02-21 16:17:08 +0100390static int qual_syscall(), qual_signal(), qual_desc();
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000391
Roland McGrathe10e62a2004-09-04 04:20:43 +0000392static const struct qual_options {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000393 int bitflag;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000394 const char *option_name;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000395 int (*qualify)(const char *, int, int);
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000396 const char *argument_name;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000397} qual_options[] = {
Roland McGrath9797ceb2002-12-30 10:23:00 +0000398 { QUAL_TRACE, "trace", qual_syscall, "system call" },
399 { QUAL_TRACE, "t", qual_syscall, "system call" },
400 { QUAL_ABBREV, "abbrev", qual_syscall, "system call" },
401 { QUAL_ABBREV, "a", qual_syscall, "system call" },
402 { QUAL_VERBOSE, "verbose", qual_syscall, "system call" },
403 { QUAL_VERBOSE, "v", qual_syscall, "system call" },
404 { QUAL_RAW, "raw", qual_syscall, "system call" },
405 { QUAL_RAW, "x", qual_syscall, "system call" },
406 { QUAL_SIGNAL, "signal", qual_signal, "signal" },
407 { QUAL_SIGNAL, "signals", qual_signal, "signal" },
408 { QUAL_SIGNAL, "s", qual_signal, "signal" },
Roland McGrath9797ceb2002-12-30 10:23:00 +0000409 { QUAL_READ, "read", qual_desc, "descriptor" },
410 { QUAL_READ, "reads", qual_desc, "descriptor" },
411 { QUAL_READ, "r", qual_desc, "descriptor" },
412 { QUAL_WRITE, "write", qual_desc, "descriptor" },
413 { QUAL_WRITE, "writes", qual_desc, "descriptor" },
414 { QUAL_WRITE, "w", qual_desc, "descriptor" },
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000415 { 0, NULL, NULL, NULL },
416};
417
Roland McGrath9797ceb2002-12-30 10:23:00 +0000418static void
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100419reallocate_qual(int n)
420{
421 unsigned p;
422 qualbits_t *qp;
423 for (p = 0; p < SUPPORTED_PERSONALITIES; p++) {
424 qp = qual_vec[p] = realloc(qual_vec[p], n * sizeof(qualbits_t));
425 if (!qp)
426 die_out_of_memory();
427 memset(&qp[num_quals], 0, (n - num_quals) * sizeof(qualbits_t));
428 }
429 num_quals = n;
430}
431
432static void
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000433qualify_one(int n, int bitflag, int not, int pers)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000434{
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100435 unsigned p;
Roland McGrath138c6a32006-01-12 09:50:49 +0000436
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100437 if (num_quals <= n)
438 reallocate_qual(n + 1);
Roland McGrath138c6a32006-01-12 09:50:49 +0000439
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100440 for (p = 0; p < SUPPORTED_PERSONALITIES; p++) {
441 if (pers == p || pers < 0) {
442 if (not)
443 qual_vec[p][n] &= ~bitflag;
444 else
445 qual_vec[p][n] |= bitflag;
446 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000447 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000448}
449
450static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000451qual_syscall(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000452{
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100453 unsigned p;
454 unsigned i;
Roland McGrathfe6b3522005-02-02 04:40:11 +0000455 int rc = -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000456
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100457 if (*s >= '0' && *s <= '9') {
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100458 i = string_to_uint(s);
Denys Vlasenkob43dacd2013-02-23 18:19:28 +0100459 if (i >= MAX_NSYSCALLS)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000460 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000461 qualify_one(i, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000462 return 0;
Roland McGrath48a035f2006-01-12 09:45:56 +0000463 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000464
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100465 for (p = 0; p < SUPPORTED_PERSONALITIES; p++) {
466 for (i = 0; i < nsyscall_vec[p]; i++) {
467 if (sysent_vec[p][i].sys_name
468 && strcmp(s, sysent_vec[p][i].sys_name) == 0
469 ) {
Dmitry V. Levin7b9e45e2013-03-01 15:50:22 +0000470 qualify_one(i, bitflag, not, p);
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100471 rc = 0;
472 }
Roland McGrath138c6a32006-01-12 09:50:49 +0000473 }
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100474 }
Dmitry V. Levinc18c7032007-08-22 21:43:30 +0000475
Roland McGrathfe6b3522005-02-02 04:40:11 +0000476 return rc;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000477}
478
479static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000480qual_signal(const char *s, int bitflag, int not)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000481{
482 int i;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000483
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100484 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000485 int signo = string_to_uint(s);
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100486 if (signo < 0 || signo > 255)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000487 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000488 qualify_one(signo, bitflag, not, -1);
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +0000489 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000490 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000491 if (strncasecmp(s, "SIG", 3) == 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000492 s += 3;
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100493 for (i = 0; i <= NSIG; i++) {
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000494 if (strcasecmp(s, signame(i) + 3) == 0) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000495 qualify_one(i, bitflag, not, -1);
Roland McGrath76421df2005-02-02 03:51:18 +0000496 return 0;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000497 }
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100498 }
Roland McGrath76421df2005-02-02 03:51:18 +0000499 return -1;
Roland McGrath9797ceb2002-12-30 10:23:00 +0000500}
501
502static int
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000503qual_desc(const char *s, int bitflag, int not)
Roland McGrath9797ceb2002-12-30 10:23:00 +0000504{
Denys Vlasenkoe4cc7c52012-03-23 11:29:01 +0100505 if (*s >= '0' && *s <= '9') {
Dmitry V. Levinccee1692012-03-25 21:49:48 +0000506 int desc = string_to_uint(s);
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100507 if (desc < 0 || desc > 0x7fff) /* paranoia */
Roland McGrathfe6b3522005-02-02 04:40:11 +0000508 return -1;
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000509 qualify_one(desc, bitflag, not, -1);
Roland McGrath2b619022003-04-10 18:58:20 +0000510 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000511 }
512 return -1;
513}
514
515static int
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000516lookup_class(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000517{
518 if (strcmp(s, "file") == 0)
519 return TRACE_FILE;
520 if (strcmp(s, "ipc") == 0)
521 return TRACE_IPC;
522 if (strcmp(s, "network") == 0)
523 return TRACE_NETWORK;
524 if (strcmp(s, "process") == 0)
525 return TRACE_PROCESS;
526 if (strcmp(s, "signal") == 0)
527 return TRACE_SIGNAL;
Roland McGrath2fe7b132005-07-05 03:25:35 +0000528 if (strcmp(s, "desc") == 0)
529 return TRACE_DESC;
Namhyung Kim96792962012-10-24 11:41:57 +0900530 if (strcmp(s, "memory") == 0)
531 return TRACE_MEMORY;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000532 return -1;
533}
534
535void
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000536qualify(const char *s)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000537{
Roland McGrathe10e62a2004-09-04 04:20:43 +0000538 const struct qual_options *opt;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000539 int not;
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000540 char *copy;
541 const char *p;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000542 int i, n;
543
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100544 if (num_quals == 0)
545 reallocate_qual(MIN_QUALS);
546
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000547 opt = &qual_options[0];
548 for (i = 0; (p = qual_options[i].option_name); i++) {
549 n = strlen(p);
550 if (strncmp(s, p, n) == 0 && s[n] == '=') {
551 opt = &qual_options[i];
552 s += n + 1;
553 break;
554 }
555 }
556 not = 0;
557 if (*s == '!') {
558 not = 1;
559 s++;
560 }
561 if (strcmp(s, "none") == 0) {
562 not = 1 - not;
563 s = "all";
564 }
565 if (strcmp(s, "all") == 0) {
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100566 for (i = 0; i < num_quals; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000567 qualify_one(i, opt->bitflag, not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000568 }
569 return;
570 }
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100571 for (i = 0; i < num_quals; i++) {
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000572 qualify_one(i, opt->bitflag, !not, -1);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000573 }
Denys Vlasenko5d645812011-08-20 12:48:18 +0200574 copy = strdup(s);
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200575 if (!copy)
576 die_out_of_memory();
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000577 for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000578 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100579 unsigned pers;
580 for (pers = 0; pers < SUPPORTED_PERSONALITIES; pers++) {
581 for (i = 0; i < nsyscall_vec[pers]; i++)
582 if (sysent_vec[pers][i].sys_flags & n)
Dmitry V. Levin7b9e45e2013-03-01 15:50:22 +0000583 qualify_one(i, opt->bitflag, not, pers);
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +0100584 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000585 continue;
586 }
Dmitry V. Levin35d05722010-09-15 16:18:20 +0000587 if (opt->qualify(p, opt->bitflag, not)) {
Denys Vlasenko4c65c442012-03-08 11:54:10 +0100588 error_msg_and_die("invalid %s '%s'",
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000589 opt->argument_name, p);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000590 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000591 }
Dmitry V. Levin30145dd2010-09-06 22:08:24 +0000592 free(copy);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000593 return;
594}
595
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000596#ifdef SYS_socket_subcall
Roland McGratha4d48532005-06-08 20:45:28 +0000597static void
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000598decode_socket_subcall(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000599{
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000600 unsigned long addr;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +0100601 unsigned int i, n, size;
Wichert Akkermanbf79f2e2000-09-01 21:03:06 +0000602
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000603 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
604 return;
605
606 tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
Denys Vlasenko74ec14f2013-02-21 16:13:47 +0100607 tcp->qual_flg = qual_flags[tcp->scno];
608 tcp->s_ent = &sysent[tcp->scno];
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000609 addr = tcp->u_arg[1];
Denys Vlasenko9fd4f962012-03-19 09:36:42 +0100610 size = current_wordsize;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +0100611 n = tcp->s_ent->nargs;
612 for (i = 0; i < n; ++i) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000613 if (size == sizeof(int)) {
614 unsigned int arg;
615 if (umove(tcp, addr, &arg) < 0)
616 arg = 0;
617 tcp->u_arg[i] = arg;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000618 }
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000619 else {
620 unsigned long arg;
621 if (umove(tcp, addr, &arg) < 0)
622 arg = 0;
623 tcp->u_arg[i] = arg;
624 }
625 addr += size;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000626 }
627}
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000628#endif
Mike Frysinger3362e892012-03-15 01:09:19 -0400629
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000630#ifdef SYS_ipc_subcall
631static void
632decode_ipc_subcall(struct tcb *tcp)
633{
Denys Vlasenko74ec14f2013-02-21 16:13:47 +0100634 unsigned int i, n;
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000635
636 if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
637 return;
638
639 tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
Denys Vlasenko74ec14f2013-02-21 16:13:47 +0100640 tcp->qual_flg = qual_flags[tcp->scno];
641 tcp->s_ent = &sysent[tcp->scno];
642 n = tcp->s_ent->nargs;
643 for (i = 0; i < n; i++)
Dmitry V. Levin648c22c2012-03-15 22:08:55 +0000644 tcp->u_arg[i] = tcp->u_arg[i + 1];
645}
646#endif
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000647
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200648int
649printargs(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000650{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200651 if (entering(tcp)) {
652 int i;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +0100653 int n = tcp->s_ent->nargs;
654 for (i = 0; i < n; i++)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200655 tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
656 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000657 return 0;
658}
659
Denys Vlasenko72879c62012-02-27 14:18:02 +0100660int
661printargs_lu(struct tcb *tcp)
662{
663 if (entering(tcp)) {
664 int i;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +0100665 int n = tcp->s_ent->nargs;
666 for (i = 0; i < n; i++)
Denys Vlasenko72879c62012-02-27 14:18:02 +0100667 tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
668 }
669 return 0;
670}
671
672int
673printargs_ld(struct tcb *tcp)
674{
675 if (entering(tcp)) {
676 int i;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +0100677 int n = tcp->s_ent->nargs;
678 for (i = 0; i < n; i++)
Denys Vlasenko72879c62012-02-27 14:18:02 +0100679 tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
680 }
681 return 0;
682}
683
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100684#if defined(SPARC) || defined(SPARC64) || defined(IA64) || defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200685long
686getrval2(struct tcb *tcp)
687{
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100688 long val;
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200689
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100690# if defined(SPARC) || defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100691 val = sparc_regs.u_regs[U_REG_O1];
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100692# elif defined(SH)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200693 if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
694 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100695# elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200696 if (upeek(tcp, PT_R9, &val) < 0)
697 return -1;
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100698# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200699
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200700 return val;
701}
Denys Vlasenko1ebe08d2013-02-05 16:55:23 +0100702#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200703
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200704int
705is_restart_error(struct tcb *tcp)
706{
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200707 switch (tcp->u_error) {
708 case ERESTARTSYS:
709 case ERESTARTNOINTR:
710 case ERESTARTNOHAND:
711 case ERESTART_RESTARTBLOCK:
712 return 1;
713 default:
714 break;
715 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +0200716 return 0;
717}
718
Denys Vlasenko523635f2012-02-25 02:44:25 +0100719#if defined(I386)
Denys Vlasenko2550d482013-02-15 21:04:28 +0100720struct user_regs_struct i386_regs;
H.J. Lu35be5812012-04-16 13:00:01 +0200721#elif defined(X86_64) || defined(X32)
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100722/*
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100723 * On i386, pt_regs and user_regs_struct are the same,
724 * but on 64 bit x86, user_regs_struct has six more fields:
Denys Vlasenkoe73a89d2012-01-18 11:07:24 +0100725 * fs_base, gs_base, ds, es, fs, gs.
726 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
727 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100728struct i386_user_regs_struct {
729 uint32_t ebx;
730 uint32_t ecx;
731 uint32_t edx;
732 uint32_t esi;
733 uint32_t edi;
734 uint32_t ebp;
735 uint32_t eax;
736 uint32_t xds;
737 uint32_t xes;
738 uint32_t xfs;
739 uint32_t xgs;
740 uint32_t orig_eax;
741 uint32_t eip;
742 uint32_t xcs;
743 uint32_t eflags;
744 uint32_t esp;
745 uint32_t xss;
746};
747static union {
748 struct user_regs_struct x86_64_r;
749 struct i386_user_regs_struct i386_r;
750} x86_regs_union;
751# define x86_64_regs x86_regs_union.x86_64_r
752# define i386_regs x86_regs_union.i386_r
753static struct iovec x86_io = {
754 .iov_base = &x86_regs_union
755};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100756#elif defined(IA64)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200757long ia32 = 0; /* not static */
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100758static long ia64_r8, ia64_r10;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100759#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +0100760static long ppc_result;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100761#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100762static long m68k_d0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100763#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100764static long bfin_r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100765#elif defined(ARM)
Denys Vlasenko401374e2013-02-06 18:24:39 +0100766struct pt_regs arm_regs; /* not static */
Steve McIntyred8d3bd32012-10-24 17:58:16 +0100767#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100768static union {
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100769 struct user_pt_regs aarch64_r;
770 struct arm_pt_regs arm_r;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100771} arm_regs_union;
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100772# define aarch64_regs arm_regs_union.aarch64_r
773# define arm_regs arm_regs_union.arm_r
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100774static struct iovec aarch64_io = {
Denys Vlasenko59aea0a2013-02-11 12:29:36 +0100775 .iov_base = &arm_regs_union
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100776};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100777#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100778static long alpha_r0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100779static long alpha_a3;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100780#elif defined(AVR32)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100781static struct pt_regs avr32_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100782#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100783struct pt_regs sparc_regs; /* not static */
Denys Vlasenko523635f2012-02-25 02:44:25 +0100784#elif defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100785static long long mips_a3;
786static long long mips_r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100787#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100788static long mips_a3;
789static long mips_r2;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100790#elif defined(S390) || defined(S390X)
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200791static long gpr2;
Denys Vlasenkob63256e2011-06-07 12:13:24 +0200792static long syscall_mode;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100793#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100794static long hppa_r28;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100795#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +0100796static long sh_r0;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100797#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100798static long sh64_r9;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100799#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100800static long cris_r10;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100801#elif defined(TILE)
802struct pt_regs tile_regs;
Denys Vlasenko523635f2012-02-25 02:44:25 +0100803#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +0100804static long microblaze_r3;
Christian Svensson492f81f2013-02-14 13:26:27 +0100805#elif defined(OR1K)
806static struct user_regs_struct or1k_regs;
807static struct iovec or1k_io = {
808 .iov_base = &or1k_regs
809};
James Hogan5f999a82013-02-22 14:44:10 +0000810#elif defined(METAG)
811static struct user_gp_regs metag_regs;
812static struct iovec metag_io = {
813 .iov_base = &metag_regs
814};
Denys Vlasenko523635f2012-02-25 02:44:25 +0100815#endif
Wichert Akkermanc7926982000-04-10 22:22:31 +0000816
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100817void
818printcall(struct tcb *tcp)
819{
820#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
821 sizeof(long) == 8 ? "[????????????????] " : \
822 NULL /* crash */)
823 if (get_regs_error) {
824 PRINTBADPC;
825 return;
826 }
827#if defined(I386)
828 tprintf("[%08lx] ", i386_regs.eip);
829#elif defined(S390) || defined(S390X)
830 long psw;
831 if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
832 PRINTBADPC;
833 return;
834 }
835# ifdef S390
836 tprintf("[%08lx] ", psw);
837# elif S390X
Dmitry V. Levinddba73e2013-02-05 19:01:58 +0000838 tprintf("[%016lx] ", psw);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100839# endif
840#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +0100841 if (x86_io.iov_len == sizeof(i386_regs)) {
842 tprintf("[%08x] ", (unsigned) i386_regs.eip);
843 } else {
844# if defined(X86_64)
845 tprintf("[%016lx] ", (unsigned long) x86_64_regs.rip);
846# elif defined(X32)
847 /* Note: this truncates 64-bit rip to 32 bits */
848 tprintf("[%08lx] ", (unsigned long) x86_64_regs.rip);
849# endif
850 }
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100851#elif defined(IA64)
852 long ip;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100853 if (upeek(tcp, PT_B0, &ip) < 0) {
854 PRINTBADPC;
855 return;
856 }
857 tprintf("[%08lx] ", ip);
858#elif defined(POWERPC)
859 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100860 if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
861 PRINTBADPC;
862 return;
863 }
864# ifdef POWERPC64
865 tprintf("[%016lx] ", pc);
866# else
867 tprintf("[%08lx] ", pc);
868# endif
869#elif defined(M68K)
870 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100871 if (upeek(tcp, 4*PT_PC, &pc) < 0) {
872 tprints("[????????] ");
873 return;
874 }
875 tprintf("[%08lx] ", pc);
876#elif defined(ALPHA)
877 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100878 if (upeek(tcp, REG_PC, &pc) < 0) {
879 tprints("[????????????????] ");
880 return;
881 }
882 tprintf("[%08lx] ", pc);
883#elif defined(SPARC)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100884 tprintf("[%08lx] ", sparc_regs.pc);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100885#elif defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100886 tprintf("[%08lx] ", sparc_regs.tpc);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100887#elif defined(HPPA)
888 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100889 if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
890 tprints("[????????] ");
891 return;
892 }
893 tprintf("[%08lx] ", pc);
894#elif defined(MIPS)
895 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100896 if (upeek(tcp, REG_EPC, &pc) < 0) {
897 tprints("[????????] ");
898 return;
899 }
900 tprintf("[%08lx] ", pc);
901#elif defined(SH)
902 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100903 if (upeek(tcp, 4*REG_PC, &pc) < 0) {
904 tprints("[????????] ");
905 return;
906 }
907 tprintf("[%08lx] ", pc);
908#elif defined(SH64)
909 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100910 if (upeek(tcp, REG_PC, &pc) < 0) {
911 tprints("[????????????????] ");
912 return;
913 }
914 tprintf("[%08lx] ", pc);
915#elif defined(ARM)
Denys Vlasenko401374e2013-02-06 18:24:39 +0100916 tprintf("[%08lx] ", arm_regs.ARM_pc);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +0100917#elif defined(AARCH64)
918 /* tprintf("[%016lx] ", aarch64_regs.regs[???]); */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100919#elif defined(AVR32)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +0100920 tprintf("[%08lx] ", avr32_regs.pc);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100921#elif defined(BFIN)
922 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100923 if (upeek(tcp, PT_PC, &pc) < 0) {
924 PRINTBADPC;
925 return;
926 }
927 tprintf("[%08lx] ", pc);
928#elif defined(CRISV10)
929 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100930 if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
931 PRINTBADPC;
932 return;
933 }
934 tprintf("[%08lx] ", pc);
935#elif defined(CRISV32)
936 long pc;
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100937 if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
938 PRINTBADPC;
939 return;
940 }
941 tprintf("[%08lx] ", pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100942#elif defined(TILE)
943# ifdef _LP64
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500944 tprintf("[%016lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100945# else
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -0500946 tprintf("[%08lx] ", (unsigned long) tile_regs.pc);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +0100947# endif
Christian Svensson492f81f2013-02-14 13:26:27 +0100948#elif defined(OR1K)
949 tprintf("[%08lx] ", or1k_regs.pc);
James Hogan5f999a82013-02-22 14:44:10 +0000950#elif defined(METAG)
951 tprintf("[%08lx] ", metag_regs.pc);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +0100952#endif /* architecture */
953}
954
Denys Vlasenko7270de52013-02-21 15:46:34 +0100955/* Shuffle syscall numbers so that we don't have huge gaps in syscall table.
956 * The shuffling should be reversible: shuffle_scno(shuffle_scno(n)) == n.
957 */
958#if defined(ARM) /* So far only ARM needs this */
959static long
960shuffle_scno(unsigned long scno)
961{
962 if (scno <= ARM_LAST_ORDINARY_SYSCALL)
963 return scno;
964
965 /* __ARM_NR_cmpxchg? Swap with LAST_ORDINARY+1 */
966 if (scno == 0x000ffff0)
967 return ARM_LAST_ORDINARY_SYSCALL+1;
968 if (scno == ARM_LAST_ORDINARY_SYSCALL+1)
969 return 0x000ffff0;
970
971 /* Is it ARM specific syscall?
972 * Swap with [LAST_ORDINARY+2, LAST_ORDINARY+2 + LAST_SPECIAL] range.
973 */
974 if (scno >= 0x000f0000
975 && scno <= 0x000f0000 + ARM_LAST_SPECIAL_SYSCALL
976 ) {
977 return scno - 0x000f0000 + (ARM_LAST_ORDINARY_SYSCALL+2);
978 }
979 if (/* scno >= ARM_LAST_ORDINARY_SYSCALL+2 - always true */ 1
980 && scno <= (ARM_LAST_ORDINARY_SYSCALL+2) + ARM_LAST_SPECIAL_SYSCALL
981 ) {
982 return scno + 0x000f0000 - (ARM_LAST_ORDINARY_SYSCALL+2);
983 }
984
985 return scno;
986}
987#else
988# define shuffle_scno(scno) ((long)(scno))
989#endif
990
991static char*
992undefined_scno_name(struct tcb *tcp)
993{
994 static char buf[sizeof("syscall_%lu") + sizeof(long)*3];
995
996 sprintf(buf, "syscall_%lu", shuffle_scno(tcp->scno));
997 return buf;
998}
999
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001000#ifndef get_regs
1001long get_regs_error;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001002void
1003get_regs(pid_t pid)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001004{
1005# if defined(AVR32)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001006 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &avr32_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001007# elif defined(I386)
1008 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &i386_regs);
1009# elif defined(X86_64) || defined(X32)
Denys Vlasenkoe3b248d2013-02-15 00:24:19 +01001010 /*
1011 * PTRACE_GETREGSET was introduced in 2.6.33.
1012 * Let's be paranoid and require a bit later kernel.
1013 */
1014 if (os_release >= KERNEL_VERSION(2,6,35)) {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001015 /*x86_io.iov_base = &x86_regs_union; - already is */
1016 x86_io.iov_len = sizeof(x86_regs_union);
1017 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (long) &x86_io);
1018 } else {
1019 /* Use old method, with heuristical detection of 32-bitness */
1020 x86_io.iov_len = sizeof(x86_64_regs);
1021 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &x86_64_regs);
1022 if (!get_regs_error && x86_64_regs.cs == 0x23) {
1023 x86_io.iov_len = sizeof(i386_regs);
1024 /*
1025 * The order is important: i386_regs and x86_64_regs
1026 * are overlaid in memory!
1027 */
1028 i386_regs.ebx = x86_64_regs.rbx;
1029 i386_regs.ecx = x86_64_regs.rcx;
1030 i386_regs.edx = x86_64_regs.rdx;
1031 i386_regs.esi = x86_64_regs.rsi;
1032 i386_regs.edi = x86_64_regs.rdi;
1033 i386_regs.ebp = x86_64_regs.rbp;
1034 i386_regs.eax = x86_64_regs.rax;
1035 /*i386_regs.xds = x86_64_regs.ds; unused by strace */
1036 /*i386_regs.xes = x86_64_regs.es; ditto... */
1037 /*i386_regs.xfs = x86_64_regs.fs;*/
1038 /*i386_regs.xgs = x86_64_regs.gs;*/
1039 i386_regs.orig_eax = x86_64_regs.orig_rax;
1040 i386_regs.eip = x86_64_regs.rip;
1041 /*i386_regs.xcs = x86_64_regs.cs;*/
1042 /*i386_regs.eflags = x86_64_regs.eflags;*/
1043 i386_regs.esp = x86_64_regs.rsp;
1044 /*i386_regs.xss = x86_64_regs.ss;*/
1045 }
1046 }
Denys Vlasenko401374e2013-02-06 18:24:39 +01001047# elif defined(ARM)
1048 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (void *)&arm_regs);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001049# elif defined(AARCH64)
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001050 /*aarch64_io.iov_base = &arm_regs_union; - already is */
1051 aarch64_io.iov_len = sizeof(arm_regs_union);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001052 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void *)&aarch64_io);
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001053# if 0
1054 /* Paranoia checks */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001055 if (get_regs_error)
1056 return;
1057 switch (aarch64_io.iov_len) {
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001058 case sizeof(aarch64_regs):
1059 /* We are in 64-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001060 break;
1061 case sizeof(arm_regs):
1062 /* We are in 32-bit mode */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001063 break;
1064 default:
1065 get_regs_error = -1;
1066 break;
1067 }
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001068# endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001069# elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001070 get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&sparc_regs, 0);
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001071# elif defined(TILE)
Chris Metcalfaf8dc6b2013-02-05 13:02:42 -05001072 get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &tile_regs);
Christian Svensson492f81f2013-02-14 13:26:27 +01001073# elif defined(OR1K)
1074 or1k_io.iov_len = sizeof(or1k_regs);
1075 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &or1k_io);
James Hogan5f999a82013-02-22 14:44:10 +00001076# elif defined(METAG)
1077 metag_io.iov_len = sizeof(metag_regs);
1078 get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &metag_io);
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001079# endif
1080}
1081#endif
1082
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001083/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001084 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1085 * 1: ok, continue in trace_syscall_entering().
1086 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001087 * ("????" etc) and bail out.
1088 */
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01001089static int
Denys Vlasenko06602d92011-08-24 17:53:52 +02001090get_scno(struct tcb *tcp)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001091{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001092 long scno = 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001093
Denys Vlasenko523635f2012-02-25 02:44:25 +01001094#if defined(S390) || defined(S390X)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001095 if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001096 return -1;
Roland McGrath2f924ca2003-06-26 22:23:28 +00001097
1098 if (syscall_mode != -ENOSYS) {
1099 /*
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001100 * Since kernel version 2.5.44 the scno gets passed in gpr2.
Roland McGrath2f924ca2003-06-26 22:23:28 +00001101 */
1102 scno = syscall_mode;
1103 } else {
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001104 /*
Michal Ludvig882eda82002-11-11 12:50:47 +00001105 * Old style of "passing" the scno via the SVC instruction.
1106 */
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001107 long psw;
Michal Ludvig882eda82002-11-11 12:50:47 +00001108 long opcode, offset_reg, tmp;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001109 void *svc_addr;
Denys Vlasenko7c9ba8b2011-08-19 19:46:32 +02001110 static const int gpr_offset[16] = {
1111 PT_GPR0, PT_GPR1, PT_ORIGGPR2, PT_GPR3,
1112 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
1113 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
1114 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15
1115 };
Roland McGrath761b5d72002-12-15 23:58:31 +00001116
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001117 if (upeek(tcp, PT_PSWADDR, &psw) < 0)
Michal Ludvig882eda82002-11-11 12:50:47 +00001118 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +00001119 errno = 0;
Denys Vlasenko7ba8e722013-02-08 15:50:05 +01001120 opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(psw - sizeof(long)), 0);
Roland McGrath96dc5142003-01-20 10:23:04 +00001121 if (errno) {
Denys Vlasenko905e8e02013-02-26 12:30:09 +01001122 perror_msg("peektext(psw-oneword)");
Michal Ludvig882eda82002-11-11 12:50:47 +00001123 return -1;
Roland McGrath96dc5142003-01-20 10:23:04 +00001124 }
Michal Ludvig882eda82002-11-11 12:50:47 +00001125
1126 /*
1127 * We have to check if the SVC got executed directly or via an
1128 * EXECUTE instruction. In case of EXECUTE it is necessary to do
1129 * instruction decoding to derive the system call number.
1130 * Unfortunately the opcode sizes of EXECUTE and SVC are differently,
1131 * so that this doesn't work if a SVC opcode is part of an EXECUTE
1132 * opcode. Since there is no way to find out the opcode size this
1133 * is the best we can do...
1134 */
Michal Ludvig882eda82002-11-11 12:50:47 +00001135 if ((opcode & 0xff00) == 0x0a00) {
1136 /* SVC opcode */
1137 scno = opcode & 0xff;
Roland McGrath761b5d72002-12-15 23:58:31 +00001138 }
Michal Ludvig882eda82002-11-11 12:50:47 +00001139 else {
1140 /* SVC got executed by EXECUTE instruction */
1141
1142 /*
1143 * Do instruction decoding of EXECUTE. If you really want to
1144 * understand this, read the Principles of Operations.
1145 */
1146 svc_addr = (void *) (opcode & 0xfff);
1147
1148 tmp = 0;
1149 offset_reg = (opcode & 0x000f0000) >> 16;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001150 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001151 return -1;
1152 svc_addr += tmp;
1153
1154 tmp = 0;
1155 offset_reg = (opcode & 0x0000f000) >> 12;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001156 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001157 return -1;
1158 svc_addr += tmp;
1159
Denys Vlasenkofb036672009-01-23 16:30:26 +00001160 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
Michal Ludvig882eda82002-11-11 12:50:47 +00001161 if (errno)
1162 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001163# if defined(S390X)
Michal Ludvig882eda82002-11-11 12:50:47 +00001164 scno >>= 48;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001165# else
Michal Ludvig882eda82002-11-11 12:50:47 +00001166 scno >>= 16;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001167# endif
Michal Ludvig882eda82002-11-11 12:50:47 +00001168 tmp = 0;
1169 offset_reg = (opcode & 0x00f00000) >> 20;
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001170 if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
Michal Ludvig882eda82002-11-11 12:50:47 +00001171 return -1;
1172
1173 scno = (scno | tmp) & 0xff;
1174 }
1175 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001176#elif defined(POWERPC)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001177 if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001178 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001179# ifdef POWERPC64
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001180 /* TODO: speed up strace by not doing this at every syscall.
1181 * We only need to do it after execve.
1182 */
1183 int currpers;
1184 long val;
Andreas Schwabd69fa492010-07-12 21:39:57 +02001185
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001186 /* Check for 64/32 bit mode. */
1187 if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
1188 return -1;
1189 /* SF is bit 0 of MSR */
1190 if (val < 0)
1191 currpers = 0;
1192 else
1193 currpers = 1;
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001194 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001195# endif
1196#elif defined(AVR32)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001197 scno = avr32_regs.r8;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001198#elif defined(BFIN)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001199 if (upeek(tcp, PT_ORIG_P0, &scno))
Dmitry V. Levin87ea1f42008-11-10 22:21:41 +00001200 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001201#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001202 scno = i386_regs.orig_eax;
H.J. Lu35be5812012-04-16 13:00:01 +02001203#elif defined(X86_64) || defined(X32)
1204# ifndef __X32_SYSCALL_BIT
1205# define __X32_SYSCALL_BIT 0x40000000
1206# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001207 int currpers;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001208# if 1
1209 /* GETREGSET of NT_PRSTATUS tells us regset size,
1210 * which unambiguously detects i386.
1211 *
1212 * Linux kernel distinguishes x86-64 and x32 processes
1213 * solely by looking at __X32_SYSCALL_BIT:
1214 * arch/x86/include/asm/compat.h::is_x32_task():
1215 * if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)
1216 * return true;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001217 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001218 if (x86_io.iov_len == sizeof(i386_regs)) {
1219 scno = i386_regs.orig_eax;
1220 currpers = 1;
1221 } else {
1222 scno = x86_64_regs.orig_rax;
1223 currpers = 0;
1224 if (scno & __X32_SYSCALL_BIT) {
1225 scno -= __X32_SYSCALL_BIT;
1226 currpers = 2;
1227 }
1228 }
1229# elif 0
1230 /* cs = 0x33 for long mode (native 64 bit and x32)
1231 * cs = 0x23 for compatibility mode (32 bit)
1232 * ds = 0x2b for x32 mode (x86-64 in 32 bit)
1233 */
1234 scno = x86_64_regs.orig_rax;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001235 switch (x86_64_regs.cs) {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001236 case 0x23: currpers = 1; break;
H.J. Lu35be5812012-04-16 13:00:01 +02001237 case 0x33:
1238 if (x86_64_regs.ds == 0x2b) {
1239 currpers = 2;
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001240 scno &= ~__X32_SYSCALL_BIT;
H.J. Lu35be5812012-04-16 13:00:01 +02001241 } else
1242 currpers = 0;
1243 break;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001244 default:
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001245 fprintf(stderr, "Unknown value CS=0x%08X while "
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001246 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001247 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001248 currpers = current_personality;
1249 break;
1250 }
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001251# elif 0
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001252 /* This version analyzes the opcode of a syscall instruction.
1253 * (int 0x80 on i386 vs. syscall on x86-64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001254 * It works, but is too complicated, and strictly speaking, unreliable.
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001255 */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001256 unsigned long call, rip = x86_64_regs.rip;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001257 /* sizeof(syscall) == sizeof(int 0x80) == 2 */
1258 rip -= 2;
1259 errno = 0;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001260 call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001261 if (errno)
1262 fprintf(stderr, "ptrace_peektext failed: %s\n",
1263 strerror(errno));
1264 switch (call & 0xffff) {
1265 /* x86-64: syscall = 0x0f 0x05 */
1266 case 0x050f: currpers = 0; break;
1267 /* i386: int 0x80 = 0xcd 0x80 */
1268 case 0x80cd: currpers = 1; break;
1269 default:
1270 currpers = current_personality;
1271 fprintf(stderr,
1272 "Unknown syscall opcode (0x%04X) while "
1273 "detecting personality of process "
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001274 "PID=%d\n", (int)call, tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001275 break;
1276 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001277# endif
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001278
H.J. Lu35be5812012-04-16 13:00:01 +02001279# ifdef X32
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001280 /* If we are built for a x32 system, then personality 0 is x32
1281 * (not x86_64), and stracing of x86_64 apps is not supported.
1282 * Stracing of i386 apps is still supported.
H.J. Lu085e4282012-04-17 11:05:04 -07001283 */
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001284 if (currpers == 0) {
1285 fprintf(stderr, "syscall_%lu(...) in unsupported "
1286 "64-bit mode of process PID=%d\n",
1287 scno, tcp->pid);
1288 return 0;
H.J. Lu35be5812012-04-16 13:00:01 +02001289 }
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001290 currpers &= ~2; /* map 2,1 to 0,1 */
H.J. Lu35be5812012-04-16 13:00:01 +02001291# endif
H.J. Lu085e4282012-04-17 11:05:04 -07001292 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001293#elif defined(IA64)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001294# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01001295 long psr;
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001296 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001297 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001298 if (ia32) {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001299 if (upeek(tcp, PT_R1, &scno) < 0)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001300 return -1;
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001301 } else {
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001302 if (upeek(tcp, PT_R15, &scno) < 0)
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001303 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001304 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001305#elif defined(AARCH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001306 switch (aarch64_io.iov_len) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001307 case sizeof(aarch64_regs):
1308 /* We are in 64-bit mode */
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001309 scno = aarch64_regs.regs[8];
1310 update_personality(tcp, 1);
1311 break;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001312 case sizeof(arm_regs):
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001313 /* We are in 32-bit mode */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001314 scno = arm_regs.ARM_r7;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001315 update_personality(tcp, 0);
1316 break;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001317 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001318#elif defined(ARM)
Denys Vlasenkoe7030e52013-02-20 18:08:25 +01001319 if (arm_regs.ARM_ip != 0) {
1320 /* It is not a syscall entry */
1321 fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001322 tcp->flags |= TCB_INSYSCALL;
Denys Vlasenkoe7030e52013-02-20 18:08:25 +01001323 return 0;
1324 }
1325 /* Note: we support only 32-bit CPUs, not 26-bit */
1326
1327 if (arm_regs.ARM_cpsr & 0x20) {
1328 /* Thumb mode */
1329 scno = arm_regs.ARM_r7;
1330 } else {
1331 /* ARM mode */
1332 errno = 0;
1333 scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(arm_regs.ARM_pc - 4), NULL);
1334 if (errno)
1335 return -1;
1336
1337 /* EABI syscall convention? */
1338 if (scno == 0xef000000) {
1339 scno = arm_regs.ARM_r7; /* yes */
1340 } else {
1341 if ((scno & 0x0ff00000) != 0x0f900000) {
1342 fprintf(stderr, "pid %d unknown syscall trap 0x%08lx\n",
1343 tcp->pid, scno);
1344 return -1;
1345 }
1346 /* Fixup the syscall number */
1347 scno &= 0x000fffff;
1348 }
1349 }
Denys Vlasenko7270de52013-02-21 15:46:34 +01001350
1351 scno = shuffle_scno(scno);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001352#elif defined(M68K)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001353 if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001354 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001355#elif defined(LINUX_MIPSN32)
Roland McGrath542c2c62008-05-20 01:11:56 +00001356 unsigned long long regs[38];
1357
Denys Vlasenkob63256e2011-06-07 12:13:24 +02001358 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001359 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001360 mips_a3 = regs[REG_A3];
1361 mips_r2 = regs[REG_V0];
Roland McGrath542c2c62008-05-20 01:11:56 +00001362
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001363 scno = mips_r2;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001364 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001365 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001366 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001367 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001368 return 0;
1369 }
Roland McGrath542c2c62008-05-20 01:11:56 +00001370 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001371#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001372 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001373 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001374 if (upeek(tcp, REG_V0, &scno) < 0)
1375 return -1;
Wichert Akkermanf90da011999-10-31 21:15:38 +00001376
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001377 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01001378 if (mips_a3 == 0 || mips_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001379 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001380 fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
Roland McGrath542c2c62008-05-20 01:11:56 +00001381 return 0;
1382 }
Wichert Akkermanf90da011999-10-31 21:15:38 +00001383 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001384#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001385 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001386 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001387 if (upeek(tcp, REG_R0, &scno) < 0)
1388 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001389
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001390 /*
1391 * Do some sanity checks to figure out if it's
1392 * really a syscall entry
1393 */
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001394 if (!SCNO_IN_RANGE(scno)) {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001395 if (alpha_a3 == 0 || alpha_a3 == -1) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001396 if (debug_flag)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001397 fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001398 return 0;
1399 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001400 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001401#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001402 /* Disassemble the syscall trap. */
1403 /* Retrieve the syscall trap instruction. */
Denys Vlasenko46455822013-02-05 17:02:59 +01001404 unsigned long trap;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001405 errno = 0;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001406# if defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001407 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)sparc_regs.tpc, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001408 trap >>= 32;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001409# else
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001410 trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)sparc_regs.pc, 0);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001411# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001412 if (errno)
Wichert Akkermanc1652e22001-03-27 12:17:16 +00001413 return -1;
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001414
1415 /* Disassemble the trap to see what personality to use. */
1416 switch (trap) {
1417 case 0x91d02010:
1418 /* Linux/SPARC syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001419 update_personality(tcp, 0);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001420 break;
1421 case 0x91d0206d:
1422 /* Linux/SPARC64 syscall trap. */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001423 update_personality(tcp, 2);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001424 break;
1425 case 0x91d02000:
1426 /* SunOS syscall trap. (pers 1) */
1427 fprintf(stderr, "syscall: SunOS no support\n");
1428 return -1;
1429 case 0x91d02008:
1430 /* Solaris 2.x syscall trap. (per 2) */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001431 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001432 break;
1433 case 0x91d02009:
1434 /* NetBSD/FreeBSD syscall trap. */
1435 fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1436 return -1;
1437 case 0x91d02027:
1438 /* Solaris 2.x gettimeofday */
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00001439 update_personality(tcp, 1);
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001440 break;
1441 default:
Denys Vlasenko523635f2012-02-25 02:44:25 +01001442# if defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001443 fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, sparc_regs.tpc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001444# else
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001445 fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, sparc_regs.pc);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001446# endif
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001447 return -1;
1448 }
1449
1450 /* Extract the system call number from the registers. */
1451 if (trap == 0x91d02027)
1452 scno = 156;
1453 else
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001454 scno = sparc_regs.u_regs[U_REG_G1];
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001455 if (scno == 0) {
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001456 scno = sparc_regs.u_regs[U_REG_O0];
1457 memmove(&sparc_regs.u_regs[U_REG_O0], &sparc_regs.u_regs[U_REG_O1], 7*sizeof(sparc_regs.u_regs[0]));
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001458 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001459#elif defined(HPPA)
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001460 if (upeek(tcp, PT_GR20, &scno) < 0)
1461 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001462#elif defined(SH)
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001463 /*
1464 * In the new syscall ABI, the system call number is in R3.
1465 */
1466 if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1467 return -1;
Wichert Akkermanccef6372002-05-01 16:39:22 +00001468
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001469 if (scno < 0) {
1470 /* Odd as it may seem, a glibc bug has been known to cause
1471 glibc to issue bogus negative syscall numbers. So for
1472 our purposes, make strace print what it *should* have been */
1473 long correct_scno = (scno & 0xff);
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001474 if (debug_flag)
Denys Vlasenko5ae2b7c2009-02-27 20:32:52 +00001475 fprintf(stderr,
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001476 "Detected glibc bug: bogus system call"
1477 " number = %ld, correcting to %ld\n",
1478 scno,
1479 correct_scno);
1480 scno = correct_scno;
1481 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001482#elif defined(SH64)
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001483 if (upeek(tcp, REG_SYSCALL, &scno) < 0)
Roland McGrathe1e584b2003-06-02 19:18:58 +00001484 return -1;
Denys Vlasenkoadedb512008-12-30 18:47:55 +00001485 scno &= 0xFFFF;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001486#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001487 if (upeek(tcp, 4*PT_R9, &scno) < 0)
1488 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001489#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001490 int currpers;
1491 scno = tile_regs.regs[10];
1492# ifdef __tilepro__
1493 currpers = 1;
1494# else
Denys Vlasenko59aea0a2013-02-11 12:29:36 +01001495# ifndef PT_FLAGS_COMPAT
1496# define PT_FLAGS_COMPAT 0x10000 /* from Linux 3.8 on */
1497# endif
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001498 if (tile_regs.flags & PT_FLAGS_COMPAT)
1499 currpers = 1;
1500 else
1501 currpers = 0;
1502# endif
1503 update_personality(tcp, currpers);
Denys Vlasenko523635f2012-02-25 02:44:25 +01001504#elif defined(MICROBLAZE)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001505 if (upeek(tcp, 0, &scno) < 0)
1506 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01001507#elif defined(OR1K)
1508 scno = or1k_regs.gpr[11];
James Hogan5f999a82013-02-22 14:44:10 +00001509#elif defined(METAG)
1510 scno = metag_regs.dx[0][1]; /* syscall number in D1Re0 (D1.0) */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001511#endif
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001512
Denys Vlasenko8cd1acd2011-08-24 16:52:57 +02001513 tcp->scno = scno;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001514 if (SCNO_IS_VALID(tcp->scno)) {
1515 tcp->s_ent = &sysent[scno];
1516 tcp->qual_flg = qual_flags[scno];
1517 } else {
Denys Vlasenkoa9fe13c2013-02-22 13:26:10 +01001518 static const struct_sysent unknown = {
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001519 .nargs = MAX_ARGS,
1520 .sys_flags = 0,
1521 .sys_func = printargs,
1522 .sys_name = "unknown", /* not used */
1523 };
1524 tcp->s_ent = &unknown;
1525 tcp->qual_flg = UNDEFINED_SCNO | QUAL_RAW | DEFAULT_QUAL_FLAGS;
1526 }
Pavel Machek4dc3b142000-02-01 17:58:41 +00001527 return 1;
1528}
1529
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02001530/* Called at each syscall entry.
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001531 * Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01001532 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1533 * 1: ok, continue in trace_syscall_entering().
1534 * other: error, trace_syscall_entering() should print error indicator
Denys Vlasenkobc161ec2009-01-02 18:02:45 +00001535 * ("????" etc) and bail out.
1536 */
Roland McGratha4d48532005-06-08 20:45:28 +00001537static int
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001538syscall_fixup_on_sysenter(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001539{
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001540 /* A common case of "not a syscall entry" is post-execve SIGTRAP */
Denys Vlasenko523635f2012-02-25 02:44:25 +01001541#if defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001542 if (i386_regs.eax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001543 if (debug_flag)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001544 fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1545 return 0;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001546 }
H.J. Lu35be5812012-04-16 13:00:01 +02001547#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001548 {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001549 long rax;
1550 if (x86_io.iov_len == sizeof(i386_regs)) {
1551 /* Sign extend from 32 bits */
1552 rax = (int32_t)i386_regs.eax;
1553 } else {
1554 /* Note: in X32 build, this truncates 64 to 32 bits */
1555 rax = x86_64_regs.rax;
1556 }
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001557 if (rax != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001558 if (debug_flag)
Denys Vlasenko18beb982011-08-24 16:59:23 +02001559 fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1560 return 0;
1561 }
Michal Ludvig0e035502002-09-23 15:41:01 +00001562 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001563#elif defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001564 /* TODO: we already fetched PT_GPR2 in get_scno
1565 * and stored it in syscall_mode, reuse it here
1566 * instead of re-fetching?
1567 */
Denys Vlasenko932fc7d2008-12-16 18:18:40 +00001568 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001569 return -1;
Michal Ludvig882eda82002-11-11 12:50:47 +00001570 if (syscall_mode != -ENOSYS)
1571 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02001572 if (gpr2 != syscall_mode) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001573 if (debug_flag)
Denys Vlasenkob88f9612011-08-21 18:03:23 +02001574 fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
Wichert Akkerman12f75d12000-02-14 16:23:40 +00001575 return 0;
1576 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001577#elif defined(M68K)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02001578 /* TODO? Eliminate upeek's in arches below like we did in x86 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001579 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001580 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001581 if (m68k_d0 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001582 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001583 fprintf(stderr, "not a syscall entry (d0 = %ld)\n", m68k_d0);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001584 return 0;
1585 }
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001586#elif defined(IA64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001587 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001588 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001589 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001590 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001591 if (ia32 && ia64_r8 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001592 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001593 fprintf(stderr, "not a syscall entry (r8 = %ld)\n", ia64_r8);
Wichert Akkerman7b3346b2001-10-09 23:47:38 +00001594 return 0;
1595 }
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001596#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001597 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001598 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001599 if (cris_r10 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001600 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001601 fprintf(stderr, "not a syscall entry (r10 = %ld)\n", cris_r10);
Denys Vlasenkoea0e6e82009-02-25 17:08:40 +00001602 return 0;
1603 }
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001604#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001605 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001606 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001607 if (microblaze_r3 != -ENOSYS) {
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01001608 if (debug_flag)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01001609 fprintf(stderr, "not a syscall entry (r3 = %ld)\n", microblaze_r3);
Edgar E. Iglesias939caba2010-07-06 14:21:07 +02001610 return 0;
1611 }
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001612#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001613 return 1;
1614}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001615
Denys Vlasenko146b9442012-03-18 22:10:48 +01001616static void
1617internal_fork(struct tcb *tcp)
1618{
1619#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1620# define ARG_FLAGS 1
1621#else
1622# define ARG_FLAGS 0
1623#endif
1624#ifndef CLONE_UNTRACED
1625# define CLONE_UNTRACED 0x00800000
1626#endif
1627 if ((ptrace_setoptions
1628 & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1629 == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1630 return;
1631
1632 if (!followfork)
1633 return;
1634
1635 if (entering(tcp)) {
1636 /*
1637 * We won't see the new child if clone is called with
1638 * CLONE_UNTRACED, so we keep the same logic with that option
1639 * and don't trace it.
1640 */
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001641 if ((tcp->s_ent->sys_func == sys_clone)
1642 && (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED)
1643 )
Denys Vlasenko146b9442012-03-18 22:10:48 +01001644 return;
1645 setbpt(tcp);
1646 } else {
1647 if (tcp->flags & TCB_BPTSET)
1648 clearbpt(tcp);
1649 }
1650}
1651
1652#if defined(TCB_WAITEXECVE)
1653static void
1654internal_exec(struct tcb *tcp)
1655{
1656 /* Maybe we have post-execve SIGTRAP suppressed? */
1657 if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1658 return; /* yes, no need to do anything */
1659
1660 if (exiting(tcp) && syserror(tcp))
1661 /* Error in execve, no post-execve SIGTRAP expected */
1662 tcp->flags &= ~TCB_WAITEXECVE;
1663 else
1664 tcp->flags |= TCB_WAITEXECVE;
1665}
1666#endif
1667
1668static void
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001669syscall_fixup_for_fork_exec(struct tcb *tcp)
Roland McGrathc1e45922008-05-27 23:18:29 +00001670{
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001671 /*
1672 * We must always trace a few critical system calls in order to
1673 * correctly support following forks in the presence of tracing
1674 * qualifiers.
1675 */
1676 int (*func)();
1677
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001678 func = tcp->s_ent->sys_func;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001679
1680 if ( sys_fork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001681 || sys_vfork == func
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001682 || sys_clone == func
Denys Vlasenko146b9442012-03-18 22:10:48 +01001683 ) {
1684 internal_fork(tcp);
1685 return;
1686 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001687
Denys Vlasenko84703742012-02-25 02:38:52 +01001688#if defined(TCB_WAITEXECVE)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001689 if ( sys_execve == func
Denys Vlasenko84703742012-02-25 02:38:52 +01001690# if defined(SPARC) || defined(SPARC64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02001691 || sys_execv == func
Denys Vlasenkoa7949742011-08-21 17:26:55 +02001692# endif
Denys Vlasenko146b9442012-03-18 22:10:48 +01001693 ) {
1694 internal_exec(tcp);
1695 return;
1696 }
Roland McGrathc1e45922008-05-27 23:18:29 +00001697#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001698}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001699
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001700/* Return -1 on error or 1 on success (never 0!) */
Roland McGratha4d48532005-06-08 20:45:28 +00001701static int
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01001702get_syscall_args(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00001703{
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001704 int i, nargs;
1705
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001706 nargs = tcp->s_ent->nargs;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001707
Denys Vlasenko523635f2012-02-25 02:44:25 +01001708#if defined(S390) || defined(S390X)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001709 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001710 if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1711 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001712#elif defined(ALPHA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001713 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001714 if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1715 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001716#elif defined(IA64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001717 if (!ia32) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001718 unsigned long *out0, cfm, sof, sol;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001719 long rbs_end;
1720 /* be backwards compatible with kernel < 2.4.4... */
1721# ifndef PT_RBS_END
1722# define PT_RBS_END PT_AR_BSP
1723# endif
Wichert Akkerman8b1b40c2000-02-03 21:58:30 +00001724
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001725 if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1726 return -1;
1727 if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
Roland McGrath542c2c62008-05-20 01:11:56 +00001728 return -1;
1729
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001730 sof = (cfm >> 0) & 0x7f;
1731 sol = (cfm >> 7) & 0x7f;
1732 out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1733
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001734 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001735 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1736 sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1737 return -1;
1738 }
1739 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001740 static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1741 PT_R9 /* ECX = out1 */,
1742 PT_R10 /* EDX = out2 */,
1743 PT_R14 /* ESI = out3 */,
1744 PT_R15 /* EDI = out4 */,
1745 PT_R13 /* EBP = out5 */};
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001746
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001747 for (i = 0; i < nargs; ++i) {
1748 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1749 return -1;
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001750 /* truncate away IVE sign-extension */
1751 tcp->u_arg[i] &= 0xffffffff;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001752 }
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001753 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001754#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001755 /* N32 and N64 both use up to six registers. */
1756 unsigned long long regs[38];
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001757
1758 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1759 return -1;
1760
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001761 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001762 tcp->u_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001763# if defined(LINUX_MIPSN32)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001764 tcp->ext_arg[i] = regs[REG_A0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001765# endif
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001766 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001767#elif defined(MIPS)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001768 if (nargs > 4) {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001769 long sp;
1770
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001771 if (upeek(tcp, REG_SP, &sp) < 0)
1772 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001773 for (i = 0; i < 4; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001774 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1775 return -1;
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001776 umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001777 (char *)(tcp->u_arg + 4));
1778 } else {
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001779 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001780 if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001781 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001782 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001783#elif defined(POWERPC)
1784# ifndef PT_ORIG_R3
1785# define PT_ORIG_R3 34
1786# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001787 for (i = 0; i < nargs; ++i) {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001788 if (upeek(tcp, (i==0) ?
1789 (sizeof(unsigned long) * PT_ORIG_R3) :
1790 ((i+PT_R3) * sizeof(unsigned long)),
1791 &tcp->u_arg[i]) < 0)
1792 return -1;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001793 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001794#elif defined(SPARC) || defined(SPARC64)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001795 for (i = 0; i < nargs; ++i)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001796 tcp->u_arg[i] = sparc_regs.u_regs[U_REG_O0 + i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001797#elif defined(HPPA)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001798 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001799 if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1800 return -1;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00001801#elif defined(ARM) || defined(AARCH64)
1802# if defined(AARCH64)
1803 if (tcp->currpers == 1)
1804 for (i = 0; i < nargs; ++i)
1805 tcp->u_arg[i] = aarch64_regs.regs[i];
1806 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01001807# endif
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001808 for (i = 0; i < nargs; ++i)
Denys Vlasenko401374e2013-02-06 18:24:39 +01001809 tcp->u_arg[i] = arm_regs.uregs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001810#elif defined(AVR32)
Denys Vlasenkob5b25892011-08-30 19:04:54 +02001811 (void)i;
1812 (void)nargs;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01001813 tcp->u_arg[0] = avr32_regs.r12;
1814 tcp->u_arg[1] = avr32_regs.r11;
1815 tcp->u_arg[2] = avr32_regs.r10;
1816 tcp->u_arg[3] = avr32_regs.r9;
1817 tcp->u_arg[4] = avr32_regs.r5;
1818 tcp->u_arg[5] = avr32_regs.r3;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001819#elif defined(BFIN)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001820 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 +02001821
Denys Vlasenko4b887a52011-08-23 13:32:38 +02001822 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001823 if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1824 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001825#elif defined(SH)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001826 static const int syscall_regs[MAX_ARGS] = {
1827 4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1828 4 * (REG_REG0+7), 4 * (REG_REG0 ), 4 * (REG_REG0+1)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001829 };
1830
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001831 for (i = 0; i < nargs; ++i)
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001832 if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001833 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001834#elif defined(SH64)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001835 int i;
1836 /* Registers used by SH5 Linux system calls for parameters */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001837 static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001838
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001839 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001840 if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1841 return -1;
Denys Vlasenko6cf36052013-02-15 15:01:38 +01001842#elif defined(I386)
1843 (void)i;
1844 (void)nargs;
1845 tcp->u_arg[0] = i386_regs.ebx;
1846 tcp->u_arg[1] = i386_regs.ecx;
1847 tcp->u_arg[2] = i386_regs.edx;
1848 tcp->u_arg[3] = i386_regs.esi;
1849 tcp->u_arg[4] = i386_regs.edi;
1850 tcp->u_arg[5] = i386_regs.ebp;
H.J. Lu35be5812012-04-16 13:00:01 +02001851#elif defined(X86_64) || defined(X32)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001852 (void)i;
1853 (void)nargs;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001854 if (x86_io.iov_len != sizeof(i386_regs)) {
1855 /* x86-64 or x32 ABI */
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001856 tcp->u_arg[0] = x86_64_regs.rdi;
1857 tcp->u_arg[1] = x86_64_regs.rsi;
1858 tcp->u_arg[2] = x86_64_regs.rdx;
1859 tcp->u_arg[3] = x86_64_regs.r10;
1860 tcp->u_arg[4] = x86_64_regs.r8;
1861 tcp->u_arg[5] = x86_64_regs.r9;
H.J. Lu35be5812012-04-16 13:00:01 +02001862# ifdef X32
1863 tcp->ext_arg[0] = x86_64_regs.rdi;
1864 tcp->ext_arg[1] = x86_64_regs.rsi;
1865 tcp->ext_arg[2] = x86_64_regs.rdx;
1866 tcp->ext_arg[3] = x86_64_regs.r10;
1867 tcp->ext_arg[4] = x86_64_regs.r8;
1868 tcp->ext_arg[5] = x86_64_regs.r9;
1869# endif
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01001870 } else {
1871 /* i386 ABI */
Denys Vlasenko6cf36052013-02-15 15:01:38 +01001872 /* Zero-extend from 32 bits */
1873 /* Use widen_to_long(tcp->u_arg[N]) in syscall handlers
1874 * if you need to use *sign-extended* parameter.
1875 */
1876 tcp->u_arg[0] = (long)(uint32_t)i386_regs.ebx;
1877 tcp->u_arg[1] = (long)(uint32_t)i386_regs.ecx;
1878 tcp->u_arg[2] = (long)(uint32_t)i386_regs.edx;
1879 tcp->u_arg[3] = (long)(uint32_t)i386_regs.esi;
1880 tcp->u_arg[4] = (long)(uint32_t)i386_regs.edi;
1881 tcp->u_arg[5] = (long)(uint32_t)i386_regs.ebp;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02001882 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001883#elif defined(MICROBLAZE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001884 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001885 if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1886 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001887#elif defined(CRISV10) || defined(CRISV32)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001888 static const int crisregs[MAX_ARGS] = {
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001889 4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
Denys Vlasenko0b6c73c2011-06-23 22:22:34 +02001890 4*PT_R13 , 4*PT_MOF, 4*PT_SRP
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001891 };
Roland McGrathe1e584b2003-06-02 19:18:58 +00001892
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001893 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001894 if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1895 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001896#elif defined(TILE)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001897 for (i = 0; i < nargs; ++i)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01001898 tcp->u_arg[i] = tile_regs.regs[i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001899#elif defined(M68K)
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001900 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001901 if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1902 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01001903#elif defined(OR1K)
1904 (void)nargs;
1905 for (i = 0; i < 6; ++i)
1906 tcp->u_arg[i] = or1k_regs.gpr[3 + i];
James Hogan5f999a82013-02-22 14:44:10 +00001907#elif defined(METAG)
1908 for (i = 0; i < nargs; i++)
1909 /* arguments go backwards from D1Ar1 (D1.3) */
1910 tcp->u_arg[i] = ((unsigned long *)&metag_regs.dx[3][1])[-i];
Denys Vlasenko523635f2012-02-25 02:44:25 +01001911#else /* Other architecture (32bits specific) */
Dmitry V. Levin5f731c42011-08-23 16:24:20 +00001912 for (i = 0; i < nargs; ++i)
Denys Vlasenkof5d099c2011-06-23 22:10:54 +02001913 if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1914 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01001915#endif
Pavel Machek4dc3b142000-02-01 17:58:41 +00001916 return 1;
1917}
1918
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00001919static int
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001920trace_syscall_entering(struct tcb *tcp)
1921{
1922 int res, scno_good;
1923
Denys Vlasenko2ce12ed2011-08-24 17:25:32 +02001924#if defined TCB_WAITEXECVE
1925 if (tcp->flags & TCB_WAITEXECVE) {
1926 /* This is the post-execve SIGTRAP. */
1927 tcp->flags &= ~TCB_WAITEXECVE;
1928 return 0;
1929 }
1930#endif
1931
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01001932 scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001933 if (res == 0)
1934 return res;
Denys Vlasenko907735a2012-03-21 00:23:16 +01001935 if (res == 1) {
Denys Vlasenko8b4454c2011-08-25 10:40:14 +02001936 res = syscall_fixup_on_sysenter(tcp);
Denys Vlasenko907735a2012-03-21 00:23:16 +01001937 if (res == 0)
1938 return res;
1939 if (res == 1)
1940 res = get_syscall_args(tcp);
1941 }
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001942
1943 if (res != 1) {
1944 printleader(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001945 if (scno_good != 1)
Denys Vlasenkob7a6dae2012-03-20 16:48:35 +01001946 tprints("????" /* anti-trigraph gap */ "(");
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001947 else if (tcp->qual_flg & UNDEFINED_SCNO)
Denys Vlasenko7270de52013-02-21 15:46:34 +01001948 tprintf("%s(", undefined_scno_name(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001949 else
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001950 tprintf("%s(", tcp->s_ent->sys_name);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001951 /*
1952 * " <unavailable>" will be added later by the code which
1953 * detects ptrace errors.
1954 */
1955 goto ret;
1956 }
1957
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001958#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001959 while (1) {
Denys Vlasenko523635f2012-02-25 02:44:25 +01001960# ifdef SYS_socket_subcall
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001961 if (tcp->s_ent->sys_func == sys_socketcall) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001962 decode_socket_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001963 break;
1964 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001965# endif
1966# ifdef SYS_ipc_subcall
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001967 if (tcp->s_ent->sys_func == sys_ipc) {
Dmitry V. Levin648c22c2012-03-15 22:08:55 +00001968 decode_ipc_subcall(tcp);
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001969 break;
1970 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01001971# endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001972 break;
1973 }
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001974#endif
Dmitry V. Levinb5e88d42012-02-20 17:02:38 +00001975
Denys Vlasenko8d4ca0c2013-02-06 13:18:42 +01001976 if (need_fork_exec_workarounds)
1977 syscall_fixup_for_fork_exec(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001978
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001979 if (!(tcp->qual_flg & QUAL_TRACE)
1980 || (tracing_paths && !pathtrace_match(tcp))
1981 ) {
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001982 tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1983 return 0;
1984 }
1985
1986 tcp->flags &= ~TCB_FILTERED;
1987
1988 if (cflag == CFLAG_ONLY_STATS) {
1989 res = 0;
1990 goto ret;
1991 }
1992
1993 printleader(tcp);
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001994 if (tcp->qual_flg & UNDEFINED_SCNO)
Denys Vlasenko7270de52013-02-21 15:46:34 +01001995 tprintf("%s(", undefined_scno_name(tcp));
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001996 else
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01001997 tprintf("%s(", tcp->s_ent->sys_name);
1998 if ((tcp->qual_flg & QUAL_RAW) && tcp->s_ent->sys_func != sys_exit)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02001999 res = printargs(tcp);
2000 else
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002001 res = tcp->s_ent->sys_func(tcp);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002002
Dmitry V. Levinb742d8c2012-09-17 22:40:12 +00002003 fflush(tcp->outf);
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002004 ret:
2005 tcp->flags |= TCB_INSYSCALL;
2006 /* Measure the entrance time as late as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002007 if (Tflag || cflag)
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002008 gettimeofday(&tcp->etime, NULL);
2009 return res;
2010}
2011
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002012/* Returns:
Denys Vlasenko907735a2012-03-21 00:23:16 +01002013 * 1: ok, continue in trace_syscall_exiting().
2014 * -1: error, trace_syscall_exiting() should print error indicator
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002015 * ("????" etc) and bail out.
2016 */
2017static int
2018get_syscall_result(struct tcb *tcp)
2019{
Denys Vlasenko523635f2012-02-25 02:44:25 +01002020#if defined(S390) || defined(S390X)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002021 if (upeek(tcp, PT_GPR2, &gpr2) < 0)
2022 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002023#elif defined(POWERPC)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002024# define SO_MASK 0x10000000
2025 {
2026 long flags;
2027 if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
2028 return -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002029 if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002030 return -1;
2031 if (flags & SO_MASK)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002032 ppc_result = -ppc_result;
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002033 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002034#elif defined(AVR32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002035 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002036#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002037 if (upeek(tcp, PT_R0, &bfin_r0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002038 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002039#elif defined(I386)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002040 /* already done by get_regs */
H.J. Lu35be5812012-04-16 13:00:01 +02002041#elif defined(X86_64) || defined(X32)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002042 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002043#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002044# define IA64_PSR_IS ((long)1 << 34)
Denys Vlasenko4bdb6bb2013-02-06 18:09:31 +01002045 long psr;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002046 if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
2047 ia32 = (psr & IA64_PSR_IS) != 0;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002048 if (upeek(tcp, PT_R8, &ia64_r8) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002049 return -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002050 if (upeek(tcp, PT_R10, &ia64_r10) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002051 return -1;
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01002052#elif defined(ARM)
2053 /* already done by get_regs */
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002054#elif defined(AARCH64)
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01002055 /* register reading already done by get_regs */
2056
2057 /* Used to do this, but we did it on syscall entry already: */
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002058 /* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
2059 * else it's personality 0.
2060 */
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01002061 /*update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));*/
Denys Vlasenko523635f2012-02-25 02:44:25 +01002062#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002063 if (upeek(tcp, 4*PT_D0, &m68k_d0) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002064 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002065#elif defined(LINUX_MIPSN32)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002066 unsigned long long regs[38];
2067
2068 if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
2069 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002070 mips_a3 = regs[REG_A3];
2071 mips_r2 = regs[REG_V0];
Denys Vlasenko523635f2012-02-25 02:44:25 +01002072#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002073 if (upeek(tcp, REG_A3, &mips_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002074 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002075 if (upeek(tcp, REG_V0, &mips_r2) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002076 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002077#elif defined(ALPHA)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002078 if (upeek(tcp, REG_A3, &alpha_a3) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002079 return -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002080 if (upeek(tcp, REG_R0, &alpha_r0) < 0)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002081 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002082#elif defined(SPARC) || defined(SPARC64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002083 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002084#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002085 if (upeek(tcp, PT_GR28, &hppa_r28) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002086 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002087#elif defined(SH)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002088 /* new syscall ABI returns result in R0 */
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002089 if (upeek(tcp, 4*REG_REG0, (long *)&sh_r0) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002090 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002091#elif defined(SH64)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002092 /* ABI defines result returned in r9 */
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002093 if (upeek(tcp, REG_GENERAL(9), (long *)&sh64_r9) < 0)
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002094 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002095#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002096 if (upeek(tcp, 4*PT_R10, &cris_r10) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002097 return -1;
Denys Vlasenko523635f2012-02-25 02:44:25 +01002098#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002099 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002100#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002101 if (upeek(tcp, 3 * 4, &microblaze_r3) < 0)
Denys Vlasenkof20bff62011-08-25 10:31:24 +02002102 return -1;
Christian Svensson492f81f2013-02-14 13:26:27 +01002103#elif defined(OR1K)
2104 /* already done by get_regs */
James Hogan5f999a82013-02-22 14:44:10 +00002105#elif defined(METAG)
2106 /* already done by get_regs */
Denys Vlasenko523635f2012-02-25 02:44:25 +01002107#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002108 return 1;
2109}
2110
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002111/* Called at each syscall exit */
2112static void
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002113syscall_fixup_on_sysexit(struct tcb *tcp)
2114{
Denys Vlasenko523635f2012-02-25 02:44:25 +01002115#if defined(S390) || defined(S390X)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002116 if (syscall_mode != -ENOSYS)
2117 syscall_mode = tcp->scno;
Denys Vlasenkoece98792011-08-25 10:25:35 +02002118 if ((tcp->flags & TCB_WAITEXECVE)
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002119 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
2120 /*
2121 * Return from execve.
2122 * Fake a return value of zero. We leave the TCB_WAITEXECVE
2123 * flag set for the post-execve SIGTRAP to see and reset.
2124 */
2125 gpr2 = 0;
2126 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002127#endif
Denys Vlasenko20c41fd2011-08-25 10:23:00 +02002128}
2129
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002130/*
2131 * Check the syscall return value register value for whether it is
2132 * a negated errno code indicating an error, or a success return value.
2133 */
2134static inline int
2135is_negated_errno(unsigned long int val)
2136{
2137 unsigned long int max = -(long int) nerrnos;
Denys Vlasenko2544f982013-02-19 17:39:56 +01002138#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
Denys Vlasenko9fd4f962012-03-19 09:36:42 +01002139 if (current_wordsize < sizeof(val)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002140 val = (unsigned int) val;
2141 max = (unsigned int) max;
2142 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002143#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002144 return val > max;
2145}
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002146
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002147#if defined(X32)
2148static inline int
2149is_negated_errno_x32(unsigned long long val)
2150{
2151 unsigned long long max = -(long long) nerrnos;
2152 /*
2153 * current_wordsize is 4 even in personality 0 (native X32)
2154 * but truncation _must not_ be done in it.
2155 * can't check current_wordsize here!
2156 */
2157 if (current_personality != 0) {
2158 val = (uint32_t) val;
2159 max = (uint32_t) max;
2160 }
2161 return val > max;
2162}
2163#endif
2164
Denys Vlasenko907735a2012-03-21 00:23:16 +01002165/* Returns:
2166 * 1: ok, continue in trace_syscall_exiting().
2167 * -1: error, trace_syscall_exiting() should print error indicator
2168 * ("????" etc) and bail out.
2169 */
Denys Vlasenkoc956ef02013-02-16 14:25:56 +01002170static void
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002171get_error(struct tcb *tcp)
2172{
2173 int u_error = 0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002174 int check_errno = 1;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002175 if (tcp->s_ent->sys_flags & SYSCALL_NEVER_FAILS) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002176 check_errno = 0;
2177 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002178#if defined(S390) || defined(S390X)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002179 if (check_errno && is_negated_errno(gpr2)) {
2180 tcp->u_rval = -1;
2181 u_error = -gpr2;
2182 }
2183 else {
2184 tcp->u_rval = gpr2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002185 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002186#elif defined(I386)
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002187 if (check_errno && is_negated_errno(i386_regs.eax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002188 tcp->u_rval = -1;
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002189 u_error = -i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002190 }
2191 else {
Denys Vlasenkoeb0e3e82011-08-30 18:53:49 +02002192 tcp->u_rval = i386_regs.eax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002193 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002194#elif defined(X86_64)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002195 long rax;
2196 if (x86_io.iov_len == sizeof(i386_regs)) {
2197 /* Sign extend from 32 bits */
2198 rax = (int32_t)i386_regs.eax;
2199 } else {
2200 rax = x86_64_regs.rax;
2201 }
2202 if (check_errno && is_negated_errno(rax)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002203 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002204 u_error = -rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002205 }
2206 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002207 tcp->u_rval = rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002208 }
2209#elif defined(X32)
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002210 /* In X32, return value is 64-bit (llseek uses one).
2211 * Using merely "long rax" would not work.
2212 */
2213 long long rax;
2214 if (x86_io.iov_len == sizeof(i386_regs)) {
2215 /* Sign extend from 32 bits */
2216 rax = (int32_t)i386_regs.eax;
2217 } else {
2218 rax = x86_64_regs.rax;
2219 }
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002220 /* Careful: is_negated_errno() works only on longs */
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002221 if (check_errno && is_negated_errno_x32(rax)) {
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002222 tcp->u_rval = -1;
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002223 u_error = -rax;
Denys Vlasenkoafea7dd2013-02-12 11:52:35 +01002224 }
2225 else {
Denys Vlasenkoeec8d5d2013-02-14 03:29:48 +01002226 tcp->u_rval = rax; /* truncating */
2227 tcp->u_lrval = rax;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002228 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002229#elif defined(IA64)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002230 if (ia32) {
2231 int err;
2232
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002233 err = (int)ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002234 if (check_errno && is_negated_errno(err)) {
2235 tcp->u_rval = -1;
2236 u_error = -err;
2237 }
2238 else {
2239 tcp->u_rval = err;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002240 }
2241 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002242 if (check_errno && ia64_r10) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002243 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002244 u_error = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002245 } else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002246 tcp->u_rval = ia64_r8;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002247 }
2248 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002249#elif defined(MIPS)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002250 if (check_errno && mips_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002251 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002252 u_error = mips_r2;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002253 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002254 tcp->u_rval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002255# if defined(LINUX_MIPSN32)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002256 tcp->u_lrval = mips_r2;
H.J. Ludd0130b2012-04-16 12:16:45 +02002257# endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002258 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002259#elif defined(POWERPC)
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002260 if (check_errno && is_negated_errno(ppc_result)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002261 tcp->u_rval = -1;
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002262 u_error = -ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002263 }
2264 else {
Denys Vlasenko46dc8b22012-03-21 00:07:25 +01002265 tcp->u_rval = ppc_result;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002266 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002267#elif defined(M68K)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002268 if (check_errno && is_negated_errno(m68k_d0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002269 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002270 u_error = -m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002271 }
2272 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002273 tcp->u_rval = m68k_d0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002274 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002275#elif defined(ARM) || defined(AARCH64)
2276# if defined(AARCH64)
2277 if (tcp->currpers == 1) {
2278 if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2279 tcp->u_rval = -1;
2280 u_error = -aarch64_regs.regs[0];
2281 }
2282 else {
2283 tcp->u_rval = aarch64_regs.regs[0];
2284 }
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002285 }
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002286 else
Denys Vlasenko28ac68f2013-02-08 12:38:51 +01002287# endif
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002288 {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002289 if (check_errno && is_negated_errno(arm_regs.ARM_r0)) {
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002290 tcp->u_rval = -1;
Denys Vlasenko401374e2013-02-06 18:24:39 +01002291 u_error = -arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002292 }
2293 else {
Denys Vlasenko401374e2013-02-06 18:24:39 +01002294 tcp->u_rval = arm_regs.ARM_r0;
Steve McIntyre890a5ca2012-11-10 11:24:48 +00002295 }
Steve McIntyred8d3bd32012-10-24 17:58:16 +01002296 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002297#elif defined(AVR32)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002298 if (check_errno && avr32_regs.r12 && (unsigned) -avr32_regs.r12 < nerrnos) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002299 tcp->u_rval = -1;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002300 u_error = -avr32_regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002301 }
2302 else {
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002303 tcp->u_rval = avr32_regs.r12;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002304 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002305#elif defined(BFIN)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002306 if (check_errno && is_negated_errno(bfin_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002307 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002308 u_error = -bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002309 } else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002310 tcp->u_rval = bfin_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002311 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002312#elif defined(ALPHA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002313 if (check_errno && alpha_a3) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002314 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002315 u_error = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002316 }
2317 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002318 tcp->u_rval = alpha_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002319 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002320#elif defined(SPARC)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002321 if (check_errno && sparc_regs.psr & PSR_C) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002322 tcp->u_rval = -1;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002323 u_error = sparc_regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002324 }
2325 else {
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002326 tcp->u_rval = sparc_regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002327 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002328#elif defined(SPARC64)
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002329 if (check_errno && sparc_regs.tstate & 0x1100000000UL) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002330 tcp->u_rval = -1;
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002331 u_error = sparc_regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002332 }
2333 else {
Denys Vlasenko48e4c1b2013-02-16 08:23:40 +01002334 tcp->u_rval = sparc_regs.u_regs[U_REG_O0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002335 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002336#elif defined(HPPA)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002337 if (check_errno && is_negated_errno(hppa_r28)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002338 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002339 u_error = -hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002340 }
2341 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002342 tcp->u_rval = hppa_r28;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002343 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002344#elif defined(SH)
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002345 if (check_errno && is_negated_errno(sh_r0)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002346 tcp->u_rval = -1;
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002347 u_error = -sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002348 }
2349 else {
Denys Vlasenkod22213a2013-02-13 17:52:31 +01002350 tcp->u_rval = sh_r0;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002351 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002352#elif defined(SH64)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002353 if (check_errno && is_negated_errno(sh64_r9)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002354 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002355 u_error = -sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002356 }
2357 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002358 tcp->u_rval = sh64_r9;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002359 }
James Hogan5f999a82013-02-22 14:44:10 +00002360#elif defined(METAG)
2361 /* result pointer in D0Re0 (D0.0) */
2362 if (check_errno && is_negated_errno(metag_regs.dx[0][0])) {
2363 tcp->u_rval = -1;
2364 u_error = -metag_regs.dx[0][0];
2365 }
2366 else {
2367 tcp->u_rval = metag_regs.dx[0][0];
2368 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002369#elif defined(CRISV10) || defined(CRISV32)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002370 if (check_errno && cris_r10 && (unsigned) -cris_r10 < nerrnos) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002371 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002372 u_error = -cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002373 }
2374 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002375 tcp->u_rval = cris_r10;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002376 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002377#elif defined(TILE)
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002378 /*
2379 * The standard tile calling convention returns the value (or negative
2380 * errno) in r0, and zero (or positive errno) in r1.
2381 * Until at least kernel 3.8, however, the r1 value is not reflected
2382 * in ptregs at this point, so we use r0 here.
2383 */
2384 if (check_errno && is_negated_errno(tile_regs.regs[0])) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002385 tcp->u_rval = -1;
Chris Metcalf0b99a8a2013-02-05 17:48:33 +01002386 u_error = -tile_regs.regs[0];
2387 } else {
2388 tcp->u_rval = tile_regs.regs[0];
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002389 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002390#elif defined(MICROBLAZE)
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002391 if (check_errno && is_negated_errno(microblaze_r3)) {
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002392 tcp->u_rval = -1;
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002393 u_error = -microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002394 }
2395 else {
Denys Vlasenko89804ec2013-02-07 13:14:48 +01002396 tcp->u_rval = microblaze_r3;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002397 }
Christian Svensson492f81f2013-02-14 13:26:27 +01002398#elif defined(OR1K)
2399 if (check_errno && is_negated_errno(or1k_regs.gpr[11])) {
2400 tcp->u_rval = -1;
2401 u_error = -or1k_regs.gpr[11];
2402 }
2403 else {
2404 tcp->u_rval = or1k_regs.gpr[11];
2405 }
Denys Vlasenko523635f2012-02-25 02:44:25 +01002406#endif
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002407 tcp->u_error = u_error;
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002408}
2409
2410static void
2411dumpio(struct tcb *tcp)
2412{
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002413 int (*func)();
2414
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002415 if (syserror(tcp))
2416 return;
Denys Vlasenko9cbc15b2013-02-22 13:37:36 +01002417 if ((unsigned long) tcp->u_arg[0] >= num_quals)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002418 return;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002419 func = tcp->s_ent->sys_func;
2420 if (func == printargs)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002421 return;
2422 if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002423 if (func == sys_read ||
2424 func == sys_pread ||
2425 func == sys_recv ||
2426 func == sys_recvfrom)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002427 dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002428 else if (func == sys_readv)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002429 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2430 return;
2431 }
2432 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002433 if (func == sys_write ||
2434 func == sys_pwrite ||
2435 func == sys_send ||
2436 func == sys_sendto)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002437 dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002438 else if (func == sys_writev)
Denys Vlasenkoa6146922011-08-24 18:07:22 +02002439 dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2440 return;
2441 }
2442}
2443
Denys Vlasenkoed4f4f02011-08-22 11:54:06 +02002444static int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002445trace_syscall_exiting(struct tcb *tcp)
Pavel Machek4dc3b142000-02-01 17:58:41 +00002446{
2447 int sys_res;
2448 struct timeval tv;
Denys Vlasenko1a5b5a72011-08-25 00:29:56 +02002449 int res;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002450 long u_error;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002451
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002452 /* Measure the exit time as early as possible to avoid errors. */
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002453 if (Tflag || cflag)
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002454 gettimeofday(&tv, NULL);
Pavel Machek4dc3b142000-02-01 17:58:41 +00002455
Dmitry V. Levina5a839a2011-12-23 00:50:49 +00002456#if SUPPORTED_PERSONALITIES > 1
2457 update_personality(tcp, tcp->currpers);
2458#endif
Denys Vlasenkoce7d9532013-02-05 16:36:13 +01002459 res = (get_regs_error ? -1 : get_syscall_result(tcp));
Denys Vlasenkobb6bb5c2012-03-20 17:10:35 +01002460 if (res == 1) {
2461 syscall_fixup_on_sysexit(tcp); /* never fails */
Denys Vlasenkoc956ef02013-02-16 14:25:56 +01002462 get_error(tcp); /* never fails */
2463 if (need_fork_exec_workarounds)
2464 syscall_fixup_for_fork_exec(tcp);
2465 if (filtered(tcp))
2466 goto ret;
Pavel Machek4dc3b142000-02-01 17:58:41 +00002467 }
2468
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002469 if (cflag) {
2470 struct timeval t = tv;
Denys Vlasenkoc95a88f2011-08-21 17:47:40 +02002471 count_syscall(tcp, &t);
Denys Vlasenko7b609d52011-06-22 14:32:43 +02002472 if (cflag == CFLAG_ONLY_STATS) {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002473 goto ret;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002474 }
2475 }
2476
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002477 /* If not in -ff mode, and printing_tcp != tcp,
2478 * then the log currently does not end with output
2479 * of _our syscall entry_, but with something else.
2480 * We need to say which syscall's return is this.
2481 *
2482 * Forced reprinting via TCB_REPRINT is used only by
2483 * "strace -ff -oLOG test/threaded_execve" corner case.
2484 * It's the only case when -ff mode needs reprinting.
2485 */
2486 if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2487 tcp->flags &= ~TCB_REPRINT;
2488 printleader(tcp);
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002489 if (tcp->qual_flg & UNDEFINED_SCNO)
Denys Vlasenko7270de52013-02-21 15:46:34 +01002490 tprintf("<... %s resumed> ", undefined_scno_name(tcp));
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002491 else
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002492 tprintf("<... %s resumed> ", tcp->s_ent->sys_name);
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002493 }
2494 printing_tcp = tcp;
2495
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002496 if (res != 1) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002497 /* There was error in one of prior ptrace ops */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002498 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002499 tabto();
Denys Vlasenko000b6012012-01-28 01:25:03 +01002500 tprints("= ? <unavailable>\n");
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002501 line_ended();
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002502 tcp->flags &= ~TCB_INSYSCALL;
2503 return res;
2504 }
2505
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002506 sys_res = 0;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002507 if (tcp->qual_flg & QUAL_RAW) {
Denys Vlasenkoa44f9692012-03-21 11:06:20 +01002508 /* sys_res = printargs(tcp); - but it's nop on sysexit */
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002509 } else {
Denys Vlasenko3b738812011-08-22 02:06:35 +02002510 /* FIXME: not_failing_only (IOW, option -z) is broken:
2511 * failure of syscall is known only after syscall return.
2512 * Thus we end up with something like this on, say, ENOENT:
2513 * open("doesnt_exist", O_RDONLY <unfinished ...>
2514 * {next syscall decode}
2515 * whereas the intended result is that open(...) line
2516 * is not shown at all.
2517 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002518 if (not_failing_only && tcp->u_error)
Denys Vlasenko3b738812011-08-22 02:06:35 +02002519 goto ret; /* ignore failed syscalls */
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002520 sys_res = tcp->s_ent->sys_func(tcp);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002521 }
2522
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002523 tprints(") ");
Denys Vlasenko102ec492011-08-25 01:27:59 +02002524 tabto();
Denys Vlasenko3b738812011-08-22 02:06:35 +02002525 u_error = tcp->u_error;
Denys Vlasenko74ec14f2013-02-21 16:13:47 +01002526 if (tcp->qual_flg & QUAL_RAW) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002527 if (u_error)
2528 tprintf("= -1 (errno %ld)", u_error);
2529 else
2530 tprintf("= %#lx", tcp->u_rval);
2531 }
2532 else if (!(sys_res & RVAL_NONE) && u_error) {
2533 switch (u_error) {
Denys Vlasenkofe585652012-01-12 11:26:34 +01002534 /* Blocked signals do not interrupt any syscalls.
2535 * In this case syscalls don't return ERESTARTfoo codes.
2536 *
2537 * Deadly signals set to SIG_DFL interrupt syscalls
2538 * and kill the process regardless of which of the codes below
2539 * is returned by the interrupted syscall.
2540 * In some cases, kernel forces a kernel-generated deadly
2541 * signal to be unblocked and set to SIG_DFL (and thus cause
2542 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2543 * or SIGILL. (The alternative is to leave process spinning
2544 * forever on the faulty instruction - not useful).
2545 *
2546 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2547 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2548 * but kernel will always restart them.
2549 */
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002550 case ERESTARTSYS:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002551 /* Most common type of signal-interrupted syscall exit code.
2552 * The system call will be restarted with the same arguments
2553 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2554 */
2555 tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002556 break;
2557 case ERESTARTNOINTR:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002558 /* Rare. For example, fork() returns this if interrupted.
2559 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2560 */
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002561 tprints("= ? ERESTARTNOINTR (To be restarted)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002562 break;
2563 case ERESTARTNOHAND:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002564 /* pause(), rt_sigsuspend() etc use this code.
2565 * SA_RESTART is ignored (assumed not set):
2566 * syscall won't restart (will return EINTR instead)
Denys Vlasenko30c03232013-02-19 16:59:26 +01002567 * even after signal with SA_RESTART set. However,
2568 * after SIG_IGN or SIG_DFL signal it will restart
2569 * (thus the name "restart only if has no handler").
Denys Vlasenkofe585652012-01-12 11:26:34 +01002570 */
2571 tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002572 break;
2573 case ERESTART_RESTARTBLOCK:
Denys Vlasenkofe585652012-01-12 11:26:34 +01002574 /* Syscalls like nanosleep(), poll() which can't be
2575 * restarted with their original arguments use this
2576 * code. Kernel will execute restart_syscall() instead,
2577 * which changes arguments before restarting syscall.
2578 * SA_RESTART is ignored (assumed not set) similarly
2579 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2580 * since restart data is saved in "restart block"
2581 * in task struct, and if signal handler uses a syscall
2582 * which in turn saves another such restart block,
2583 * old data is lost and restart becomes impossible)
2584 */
2585 tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002586 break;
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002587 default:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002588 if (u_error < 0)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002589 tprintf("= -1 E??? (errno %ld)", u_error);
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002590 else if (u_error < nerrnos)
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002591 tprintf("= -1 %s (%s)", errnoent[u_error],
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002592 strerror(u_error));
2593 else
Denys Vlasenkoa7949742011-08-21 17:26:55 +02002594 tprintf("= -1 ERRNO_%ld (%s)", u_error,
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002595 strerror(u_error));
2596 break;
2597 }
2598 if ((sys_res & RVAL_STR) && tcp->auxstr)
2599 tprintf(" (%s)", tcp->auxstr);
2600 }
2601 else {
2602 if (sys_res & RVAL_NONE)
Denys Vlasenko60fe8c12011-09-01 10:00:28 +02002603 tprints("= ?");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002604 else {
2605 switch (sys_res & RVAL_MASK) {
2606 case RVAL_HEX:
2607 tprintf("= %#lx", tcp->u_rval);
2608 break;
2609 case RVAL_OCTAL:
2610 tprintf("= %#lo", tcp->u_rval);
2611 break;
2612 case RVAL_UDECIMAL:
2613 tprintf("= %lu", tcp->u_rval);
2614 break;
2615 case RVAL_DECIMAL:
2616 tprintf("= %ld", tcp->u_rval);
2617 break;
H.J. Ludd0130b2012-04-16 12:16:45 +02002618#if defined(LINUX_MIPSN32) || defined(X32)
2619 /*
2620 case RVAL_LHEX:
2621 tprintf("= %#llx", tcp->u_lrval);
2622 break;
2623 case RVAL_LOCTAL:
2624 tprintf("= %#llo", tcp->u_lrval);
2625 break;
2626 */
2627 case RVAL_LUDECIMAL:
2628 tprintf("= %llu", tcp->u_lrval);
2629 break;
2630 /*
2631 case RVAL_LDECIMAL:
2632 tprintf("= %lld", tcp->u_lrval);
2633 break;
2634 */
2635#endif
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002636 default:
2637 fprintf(stderr,
2638 "invalid rval format\n");
2639 break;
2640 }
2641 }
2642 if ((sys_res & RVAL_STR) && tcp->auxstr)
2643 tprintf(" (%s)", tcp->auxstr);
2644 }
Denys Vlasenkoa50d2a82012-03-15 12:49:52 +01002645 if (Tflag) {
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002646 tv_sub(&tv, &tv, &tcp->etime);
2647 tprintf(" <%ld.%06ld>",
2648 (long) tv.tv_sec, (long) tv.tv_usec);
2649 }
Denys Vlasenko000b6012012-01-28 01:25:03 +01002650 tprints("\n");
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002651 dumpio(tcp);
Denys Vlasenko7de265d2012-03-13 11:44:31 +01002652 line_ended();
2653
Denys Vlasenko3b738812011-08-22 02:06:35 +02002654 ret:
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002655 tcp->flags &= ~TCB_INSYSCALL;
2656 return 0;
2657}
2658
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00002659int
Dmitry V. Levin7d7c9632010-03-29 17:51:02 +00002660trace_syscall(struct tcb *tcp)
2661{
2662 return exiting(tcp) ?
2663 trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2664}