syscall.c revision b7a6dae9fb15cd9f71d72861097c6c0e8608e88e
11ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell/*
21ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
31ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
41ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
51ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
61ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
71ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell *                     Linux for s390 port by D.J. Barrow
81ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell *                    <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
91ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * All rights reserved.
101ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell *
111ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * Redistribution and use in source and binary forms, with or without
121ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * modification, are permitted provided that the following conditions
131ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * are met:
141ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * 1. Redistributions of source code must retain the above copyright
151ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell *    notice, this list of conditions and the following disclaimer.
161ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * 2. Redistributions in binary form must reproduce the above copyright
171ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell *    notice, this list of conditions and the following disclaimer in the
181ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell *    documentation and/or other materials provided with the distribution.
191ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * 3. The name of the author may not be used to endorse or promote products
201ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell *    derived from this software without specific prior written permission.
211ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell *
221ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
231ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
241ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
251ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
261ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
271ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
281ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
291ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
301ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
311ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
321ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell */
331ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
341ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#include "defs.h"
351ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#include <sys/user.h>
361ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#include <sys/param.h>
371ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
381ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#ifdef HAVE_SYS_REG_H
391ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# include <sys/reg.h>
401ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# ifndef PTRACE_PEEKUSR
411ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#  define PTRACE_PEEKUSR PTRACE_PEEKUSER
421ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# endif
431ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#elif defined(HAVE_LINUX_PTRACE_H)
441ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# undef PTRACE_SYSCALL
451ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# ifdef HAVE_STRUCT_IA64_FPREG
461ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#  define ia64_fpreg XXX_ia64_fpreg
471ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# endif
481ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
491ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#  define pt_all_user_regs XXX_pt_all_user_regs
501ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# endif
511ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# include <linux/ptrace.h>
521ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# undef ia64_fpreg
531ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# undef pt_all_user_regs
541ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
551ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
561ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#if defined(SPARC64)
571ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# undef PTRACE_GETREGS
581ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# define PTRACE_GETREGS PTRACE_GETREGS64
591ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# undef PTRACE_SETREGS
601ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# define PTRACE_SETREGS PTRACE_SETREGS64
611ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
621ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
631ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#if defined(IA64)
641ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# include <asm/ptrace_offsets.h>
651ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# include <asm/rse.h>
661ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
671ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
681ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#ifndef ERESTARTSYS
691ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# define ERESTARTSYS	512
701ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
711ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#ifndef ERESTARTNOINTR
721ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# define ERESTARTNOINTR	513
731ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
741ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#ifndef ERESTARTNOHAND
751ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# define ERESTARTNOHAND	514	/* restart if no handler */
76f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powell#endif
771ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#ifndef ERESTART_RESTARTBLOCK
781ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# define ERESTART_RESTARTBLOCK 516	/* restart by calling sys_restart_syscall */
791ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
801ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
811ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#ifndef NSIG
821ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# warning: NSIG is not defined, using 32
831ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# define NSIG 32
841ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
851ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#ifdef ARM
861ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell/* Ugh. Is this really correct? ARM has no RT signals?! */
871ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# undef NSIG
881ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# define NSIG 32
891ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
901ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
911ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#include "syscall.h"
921ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
931ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell/* Define these shorthand notations to simplify the syscallent files. */
941ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#define TD TRACE_DESC
951ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#define TF TRACE_FILE
961ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#define TI TRACE_IPC
971ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#define TN TRACE_NETWORK
981ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#define TP TRACE_PROCESS
991ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#define TS TRACE_SIGNAL
1001ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#define NF SYSCALL_NEVER_FAILS
1011ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#define MA MAX_ARGS
1021ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
1031ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic const struct sysent sysent0[] = {
1041ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#include "syscallent.h"
1051ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell};
1061ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
1071ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#if SUPPORTED_PERSONALITIES >= 2
1081ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic const struct sysent sysent1[] = {
1091ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# include "syscallent1.h"
1101ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell};
1111ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
1121ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
1131ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#if SUPPORTED_PERSONALITIES >= 3
1141ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic const struct sysent sysent2[] = {
1151ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# include "syscallent2.h"
1161ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell};
1171ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
1181ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
1191ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell/* Now undef them since short defines cause wicked namespace pollution. */
1201ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#undef TD
1211ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#undef TF
1221ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#undef TI
1231ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#undef TN
124f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powell#undef TP
125f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powell#undef TS
126f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powell#undef NF
127f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powell#undef MA
128f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powell
129f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powell/*
1301ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
1311ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * program `ioctlsort', such that the list is sorted by the `code' field.
1321ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * This has the side-effect of resolving the _IO.. macros into
1331ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * plain integers, eliminating the need to include here everything
1341ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell * in "/usr/include".
1351ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell */
1361ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
1371ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic const char *const errnoent0[] = {
1381ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#include "errnoent.h"
1391ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell};
1401ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic const char *const signalent0[] = {
1411ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#include "signalent.h"
1421ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell};
1431ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic const struct ioctlent ioctlent0[] = {
1441ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#include "ioctlent.h"
1451ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell};
1461ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellenum { nsyscalls0 = ARRAY_SIZE(sysent0) };
1471ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellenum { nerrnos0 = ARRAY_SIZE(errnoent0) };
1481ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellenum { nsignals0 = ARRAY_SIZE(signalent0) };
1491ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellenum { nioctlents0 = ARRAY_SIZE(ioctlent0) };
1501ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellint qual_flags0[MAX_QUALS];
1511ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
1521ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#if SUPPORTED_PERSONALITIES >= 2
1531ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic const char *const errnoent1[] = {
1541ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# include "errnoent1.h"
1551ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell};
1561ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic const char *const signalent1[] = {
1571ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# include "signalent1.h"
1581ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell};
1591ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic const struct ioctlent ioctlent1[] = {
1601ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# include "ioctlent1.h"
1611ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell};
1621ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellenum { nsyscalls1 = ARRAY_SIZE(sysent1) };
1631ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellenum { nerrnos1 = ARRAY_SIZE(errnoent1) };
1641ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellenum { nsignals1 = ARRAY_SIZE(signalent1) };
1651ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellenum { nioctlents1 = ARRAY_SIZE(ioctlent1) };
1661ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellint qual_flags1[MAX_QUALS];
1671ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
1681ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
1691ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#if SUPPORTED_PERSONALITIES >= 3
1701ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic const char *const errnoent2[] = {
1711ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# include "errnoent2.h"
1721ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell};
1731ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic const char *const signalent2[] = {
1741ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# include "signalent2.h"
1751ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell};
1761ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic const struct ioctlent ioctlent2[] = {
1771ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# include "ioctlent2.h"
1781ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell};
1791ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellenum { nsyscalls2 = ARRAY_SIZE(sysent2) };
1801ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellenum { nerrnos2 = ARRAY_SIZE(errnoent2) };
1811ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellenum { nsignals2 = ARRAY_SIZE(signalent2) };
1821ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellenum { nioctlents2 = ARRAY_SIZE(ioctlent2) };
1831ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellint qual_flags2[MAX_QUALS];
1841ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
1851ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
1861ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellconst struct sysent *sysent = sysent0;
1871ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellconst char *const *errnoent = errnoent0;
1881ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellconst char *const *signalent = signalent0;
1891ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellconst struct ioctlent *ioctlent = ioctlent0;
1901ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellunsigned nsyscalls = nsyscalls0;
1911ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellunsigned nerrnos = nerrnos0;
1921ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellunsigned nsignals = nsignals0;
1931ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellunsigned nioctlents = nioctlents0;
1941ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellint *qual_flags = qual_flags0;
1951ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
1961ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#if SUPPORTED_PERSONALITIES > 1
1971ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellint current_personality;
1981ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
1991ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellconst int personality_wordsize[SUPPORTED_PERSONALITIES] = {
2001ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	PERSONALITY0_WORDSIZE,
2011ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	PERSONALITY1_WORDSIZE,
2021ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# if SUPPORTED_PERSONALITIES > 2
2031ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	PERSONALITY2_WORDSIZE,
2041ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# endif
2051ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell};
2061ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
2071ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellvoid
2081ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellset_personality(int personality)
2091ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell{
2101ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	switch (personality) {
2111ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	case 0:
2121ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		errnoent = errnoent0;
2131ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		nerrnos = nerrnos0;
2141ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		sysent = sysent0;
2151ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		nsyscalls = nsyscalls0;
2161ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		ioctlent = ioctlent0;
2171ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		nioctlents = nioctlents0;
2181ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		signalent = signalent0;
2191ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		nsignals = nsignals0;
2201ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		qual_flags = qual_flags0;
2211ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		break;
2221ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
2231ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	case 1:
2241ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		errnoent = errnoent1;
2251ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		nerrnos = nerrnos1;
2261ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		sysent = sysent1;
2271ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		nsyscalls = nsyscalls1;
2281ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		ioctlent = ioctlent1;
2291ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		nioctlents = nioctlents1;
2301ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		signalent = signalent1;
2311ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		nsignals = nsignals1;
2321ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		qual_flags = qual_flags1;
2331ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		break;
2341ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
2351ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# if SUPPORTED_PERSONALITIES >= 3
2361ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	case 2:
2371ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		errnoent = errnoent2;
2381ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		nerrnos = nerrnos2;
2391ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		sysent = sysent2;
2401ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		nsyscalls = nsyscalls2;
2411ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		ioctlent = ioctlent2;
2421ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		nioctlents = nioctlents2;
2431ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		signalent = signalent2;
2441ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		nsignals = nsignals2;
2451ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		qual_flags = qual_flags2;
2461ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		break;
2471ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# endif
2481ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	}
2491ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
2501ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	current_personality = personality;
2511ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell}
2521ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
2531ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic void
2541ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellupdate_personality(struct tcb *tcp, int personality)
2551ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell{
2561ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (personality == current_personality)
2571ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		return;
2581ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	set_personality(personality);
2591ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
2601ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (personality == tcp->currpers)
2611ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		return;
2621ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	tcp->currpers = personality;
2631ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
2641ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# if defined(POWERPC64) || defined(X86_64)
2651ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (!qflag) {
2661ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		static const char *const names[] = {"64 bit", "32 bit"};
2671ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
2681ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			tcp->pid, names[personality]);
2691ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	}
2701ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell# endif
2711ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell}
2721ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
2731ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
2741ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
2751ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
2761ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic const struct qual_options {
2771ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	int bitflag;
2781ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	const char *option_name;
2791ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	int (*qualify)(const char *, int, int);
2801ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	const char *argument_name;
2811ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell} qual_options[] = {
2821ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_TRACE,	"trace",	qual_syscall,	"system call"	},
2831ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_TRACE,	"t",		qual_syscall,	"system call"	},
2841ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_ABBREV,	"abbrev",	qual_syscall,	"system call"	},
2851ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_ABBREV,	"a",		qual_syscall,	"system call"	},
2861ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_VERBOSE,	"verbose",	qual_syscall,	"system call"	},
2871ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_VERBOSE,	"v",		qual_syscall,	"system call"	},
2881ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_RAW,	"raw",		qual_syscall,	"system call"	},
2891ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_RAW,	"x",		qual_syscall,	"system call"	},
2901ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_SIGNAL,	"signal",	qual_signal,	"signal"	},
2911ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_SIGNAL,	"signals",	qual_signal,	"signal"	},
2921ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_SIGNAL,	"s",		qual_signal,	"signal"	},
2931ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_FAULT,	"fault",	qual_fault,	"fault"		},
2941ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_FAULT,	"faults",	qual_fault,	"fault"		},
2951ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_FAULT,	"m",		qual_fault,	"fault"		},
2961ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_READ,	"read",		qual_desc,	"descriptor"	},
2971ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_READ,	"reads",	qual_desc,	"descriptor"	},
2981ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_READ,	"r",		qual_desc,	"descriptor"	},
2991ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_WRITE,	"write",	qual_desc,	"descriptor"	},
3001ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_WRITE,	"writes",	qual_desc,	"descriptor"	},
3011ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ QUAL_WRITE,	"w",		qual_desc,	"descriptor"	},
3021ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	{ 0,		NULL,		NULL,		NULL		},
3031ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell};
3041ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
3051ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic void
3061ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellqualify_one(int n, int bitflag, int not, int pers)
3071ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell{
3081ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (pers == 0 || pers < 0) {
3091ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		if (not)
3101ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			qual_flags0[n] &= ~bitflag;
311f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powell		else
3121ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			qual_flags0[n] |= bitflag;
3131ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	}
3141ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
3151ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#if SUPPORTED_PERSONALITIES >= 2
3161ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (pers == 1 || pers < 0) {
3171ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		if (not)
3181ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			qual_flags1[n] &= ~bitflag;
3191ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		else
3201ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			qual_flags1[n] |= bitflag;
3211ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	}
3221ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
3231ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
3241ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#if SUPPORTED_PERSONALITIES >= 3
3251ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (pers == 2 || pers < 0) {
3261ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		if (not)
3271ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			qual_flags2[n] &= ~bitflag;
3281ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		else
3291ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			qual_flags2[n] |= bitflag;
3301ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	}
3311ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
3321ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell}
3331ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
3341ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic int
3351ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellqual_syscall(const char *s, int bitflag, int not)
3361ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell{
3371ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	int i;
3381ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	int rc = -1;
3391ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
3401ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (isdigit((unsigned char)*s)) {
3411ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		int i = atoi(s);
3421ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		if (i < 0 || i >= MAX_QUALS)
3431ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			return -1;
3441ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		qualify_one(i, bitflag, not, -1);
3451ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		return 0;
3461ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	}
3471ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	for (i = 0; i < nsyscalls0; i++)
3481ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		if (strcmp(s, sysent0[i].sys_name) == 0) {
3491ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			qualify_one(i, bitflag, not, 0);
3501ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			rc = 0;
3511ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		}
3521ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
3531ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#if SUPPORTED_PERSONALITIES >= 2
3541ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	for (i = 0; i < nsyscalls1; i++)
3551ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		if (strcmp(s, sysent1[i].sys_name) == 0) {
3561ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			qualify_one(i, bitflag, not, 1);
3571ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			rc = 0;
3581ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		}
3591ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
3601ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
3611ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#if SUPPORTED_PERSONALITIES >= 3
3621ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	for (i = 0; i < nsyscalls2; i++)
3631ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		if (strcmp(s, sysent2[i].sys_name) == 0) {
3641ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			qualify_one(i, bitflag, not, 2);
365f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powell			rc = 0;
366f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powell		}
367f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powell#endif
3681ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
3691ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	return rc;
3701ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell}
3711ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
3721ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic int
3731ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellqual_signal(const char *s, int bitflag, int not)
3741ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell{
3751ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	int i;
3761ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	char buf[32];
3771ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
3781ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (isdigit((unsigned char)*s)) {
3791ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		int signo = atoi(s);
3801ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		if (signo < 0 || signo >= MAX_QUALS)
3811ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			return -1;
3821ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		qualify_one(signo, bitflag, not, -1);
3831ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		return 0;
3841ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	}
3851ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (strlen(s) >= sizeof buf)
3861ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		return -1;
3871ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	strcpy(buf, s);
3881ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	s = buf;
3891ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (strncasecmp(s, "SIG", 3) == 0)
3901ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		s += 3;
3911ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	for (i = 0; i <= NSIG; i++)
3921ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		if (strcasecmp(s, signame(i) + 3) == 0) {
3931ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			qualify_one(i, bitflag, not, -1);
3941ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			return 0;
395f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powell		}
3961ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	return -1;
3971ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell}
3981ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
3991ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic int
4001ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellqual_fault(const char *s, int bitflag, int not)
4011ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell{
4021ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	return -1;
4031ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell}
4041ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
4051ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic int
4061ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellqual_desc(const char *s, int bitflag, int not)
4071ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell{
4081ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (isdigit((unsigned char)*s)) {
4091ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		int desc = atoi(s);
4101ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		if (desc < 0 || desc >= MAX_QUALS)
4111ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			return -1;
4121ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		qualify_one(desc, bitflag, not, -1);
4131ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		return 0;
4141ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	}
4151ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	return -1;
4161ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell}
4171ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
418f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powellstatic int
4191ce805e30800bf2852fa5421b7277a18e089ee31Adam Powelllookup_class(const char *s)
4201ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell{
4211ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (strcmp(s, "file") == 0)
4221ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		return TRACE_FILE;
4231ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (strcmp(s, "ipc") == 0)
4241ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		return TRACE_IPC;
4251ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (strcmp(s, "network") == 0)
4261ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		return TRACE_NETWORK;
4271ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (strcmp(s, "process") == 0)
4281ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		return TRACE_PROCESS;
4291ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (strcmp(s, "signal") == 0)
4301ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		return TRACE_SIGNAL;
431f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powell	if (strcmp(s, "desc") == 0)
4321ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		return TRACE_DESC;
4331ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	return -1;
4341ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell}
4351ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
4361ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellvoid
4371ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellqualify(const char *s)
4381ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell{
4391ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	const struct qual_options *opt;
4401ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	int not;
4411ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	char *copy;
4421ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	const char *p;
4431ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	int i, n;
4441ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
4451ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	opt = &qual_options[0];
4461ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	for (i = 0; (p = qual_options[i].option_name); i++) {
4471ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		n = strlen(p);
4481ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		if (strncmp(s, p, n) == 0 && s[n] == '=') {
4491ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			opt = &qual_options[i];
4501ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			s += n + 1;
4511ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			break;
4521ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		}
4531ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	}
454f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powell	not = 0;
4551ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (*s == '!') {
4561ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		not = 1;
4571ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		s++;
4581ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	}
4591ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (strcmp(s, "none") == 0) {
460f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powell		not = 1 - not;
4611ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		s = "all";
4621ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	}
463f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powell	if (strcmp(s, "all") == 0) {
4641ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		for (i = 0; i < MAX_QUALS; i++) {
4651ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			qualify_one(i, opt->bitflag, not, -1);
4661ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		}
4671ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		return;
4681ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	}
4691ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	for (i = 0; i < MAX_QUALS; i++) {
4701ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		qualify_one(i, opt->bitflag, !not, -1);
4711ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	}
4721ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	copy = strdup(s);
4731ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (!copy)
4741ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		die_out_of_memory();
4751ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
4761ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
4771ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			for (i = 0; i < nsyscalls0; i++)
4781ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell				if (sysent0[i].sys_flags & n)
4791ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell					qualify_one(i, opt->bitflag, not, 0);
4801ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
4811ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#if SUPPORTED_PERSONALITIES >= 2
4821ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			for (i = 0; i < nsyscalls1; i++)
4831ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell				if (sysent1[i].sys_flags & n)
4841ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell					qualify_one(i, opt->bitflag, not, 1);
4851ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
4861ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
4871ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#if SUPPORTED_PERSONALITIES >= 3
4881ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			for (i = 0; i < nsyscalls2; i++)
4891ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell				if (sysent2[i].sys_flags & n)
4901ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell					qualify_one(i, opt->bitflag, not, 2);
4911ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
4921ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
4931ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			continue;
4941ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		}
4951ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		if (opt->qualify(p, opt->bitflag, not)) {
4961ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			error_msg_and_die("invalid %s '%s'",
4971ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell				opt->argument_name, p);
4981ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		}
4991ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	}
5001ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	free(copy);
5011ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	return;
5021ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell}
5031ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
5041ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#ifdef SYS_socket_subcall
5051ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic void
5061ce805e30800bf2852fa5421b7277a18e089ee31Adam Powelldecode_socket_subcall(struct tcb *tcp)
5071ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell{
5081ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	unsigned long addr;
5091ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	unsigned int i, size;
5101ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
5111ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
5121ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		return;
5131ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
5141ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
515f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powell	addr = tcp->u_arg[1];
516f48af3312a4f63d8ce232fe7476932c0201774d9Adam Powell	tcp->u_nargs = sysent[tcp->scno].nargs;
5171ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	size = current_wordsize;
5181ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	for (i = 0; i < tcp->u_nargs; ++i) {
5191ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		if (size == sizeof(int)) {
5201ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			unsigned int arg;
5211ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			if (umove(tcp, addr, &arg) < 0)
5221ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell				arg = 0;
5231ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			tcp->u_arg[i] = arg;
5241ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		}
5251ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		else {
5261ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			unsigned long arg;
5271ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			if (umove(tcp, addr, &arg) < 0)
5281ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell				arg = 0;
5291ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			tcp->u_arg[i] = arg;
5301ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		}
5311ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		addr += size;
5321ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	}
5331ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell}
5341ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
5351ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
5361ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#ifdef SYS_ipc_subcall
5371ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellstatic void
5381ce805e30800bf2852fa5421b7277a18e089ee31Adam Powelldecode_ipc_subcall(struct tcb *tcp)
5391ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell{
5401ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	unsigned int i;
5411ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
5421ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
5431ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		return;
5441ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
5451ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
5461ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	tcp->u_nargs = sysent[tcp->scno].nargs;
5471ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	for (i = 0; i < tcp->u_nargs; i++)
5481ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		tcp->u_arg[i] = tcp->u_arg[i + 1];
5491ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell}
5501ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell#endif
5511ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
5521ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellint
5531ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellprintargs(struct tcb *tcp)
5541ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell{
5551ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	if (entering(tcp)) {
5561ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		int i;
5571ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
5581ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell		for (i = 0; i < tcp->u_nargs; i++)
5591ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell			tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
5601ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	}
5611ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell	return 0;
5621ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell}
5631ce805e30800bf2852fa5421b7277a18e089ee31Adam Powell
5641ce805e30800bf2852fa5421b7277a18e089ee31Adam Powellint
565printargs_lu(struct tcb *tcp)
566{
567	if (entering(tcp)) {
568		int i;
569
570		for (i = 0; i < tcp->u_nargs; i++)
571			tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
572	}
573	return 0;
574}
575
576int
577printargs_ld(struct tcb *tcp)
578{
579	if (entering(tcp)) {
580		int i;
581
582		for (i = 0; i < tcp->u_nargs; i++)
583			tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
584	}
585	return 0;
586}
587
588long
589getrval2(struct tcb *tcp)
590{
591	long val = -1;
592
593#if defined(SPARC) || defined(SPARC64)
594	struct pt_regs regs;
595	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
596		return -1;
597	val = regs.u_regs[U_REG_O1];
598#elif defined(SH)
599	if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
600		return -1;
601#elif defined(IA64)
602	if (upeek(tcp, PT_R9, &val) < 0)
603		return -1;
604#endif
605
606	return val;
607}
608
609int
610is_restart_error(struct tcb *tcp)
611{
612	switch (tcp->u_error) {
613		case ERESTARTSYS:
614		case ERESTARTNOINTR:
615		case ERESTARTNOHAND:
616		case ERESTART_RESTARTBLOCK:
617			return 1;
618		default:
619			break;
620	}
621	return 0;
622}
623
624#if defined(I386)
625struct pt_regs i386_regs;
626#elif defined(X86_64)
627/*
628 * On 32 bits, pt_regs and user_regs_struct are the same,
629 * but on 64 bits, user_regs_struct has six more fields:
630 * fs_base, gs_base, ds, es, fs, gs.
631 * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
632 */
633static struct user_regs_struct x86_64_regs;
634#elif defined(IA64)
635long r8, r10, psr; /* TODO: make static? */
636long ia32 = 0; /* not static */
637#elif defined(POWERPC)
638static long result;
639#elif defined(M68K)
640static long d0;
641#elif defined(BFIN)
642static long r0;
643#elif defined(ARM)
644static struct pt_regs regs;
645#elif defined(ALPHA)
646static long r0;
647static long a3;
648#elif defined(AVR32)
649static struct pt_regs regs;
650#elif defined(SPARC) || defined(SPARC64)
651static struct pt_regs regs;
652static unsigned long trap;
653#elif defined(LINUX_MIPSN32)
654static long long a3;
655static long long r2;
656#elif defined(MIPS)
657static long a3;
658static long r2;
659#elif defined(S390) || defined(S390X)
660static long gpr2;
661static long pc;
662static long syscall_mode;
663#elif defined(HPPA)
664static long r28;
665#elif defined(SH)
666static long r0;
667#elif defined(SH64)
668static long r9;
669#elif defined(CRISV10) || defined(CRISV32)
670static long r10;
671#elif defined(MICROBLAZE)
672static long r3;
673#endif
674
675/* Returns:
676 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
677 * 1: ok, continue in trace_syscall().
678 * other: error, trace_syscall() should print error indicator
679 *    ("????" etc) and bail out.
680 */
681static int
682get_scno(struct tcb *tcp)
683{
684	long scno = 0;
685
686#if defined(S390) || defined(S390X)
687	if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
688		return -1;
689
690	if (syscall_mode != -ENOSYS) {
691		/*
692		 * Since kernel version 2.5.44 the scno gets passed in gpr2.
693		 */
694		scno = syscall_mode;
695	} else {
696		/*
697		 * Old style of "passing" the scno via the SVC instruction.
698		 */
699		long opcode, offset_reg, tmp;
700		void *svc_addr;
701		static const int gpr_offset[16] = {
702				PT_GPR0,  PT_GPR1,  PT_ORIGGPR2, PT_GPR3,
703				PT_GPR4,  PT_GPR5,  PT_GPR6,     PT_GPR7,
704				PT_GPR8,  PT_GPR9,  PT_GPR10,    PT_GPR11,
705				PT_GPR12, PT_GPR13, PT_GPR14,    PT_GPR15
706		};
707
708		if (upeek(tcp, PT_PSWADDR, &pc) < 0)
709			return -1;
710		errno = 0;
711		opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
712		if (errno) {
713			perror("peektext(pc-oneword)");
714			return -1;
715		}
716
717		/*
718		 *  We have to check if the SVC got executed directly or via an
719		 *  EXECUTE instruction. In case of EXECUTE it is necessary to do
720		 *  instruction decoding to derive the system call number.
721		 *  Unfortunately the opcode sizes of EXECUTE and SVC are differently,
722		 *  so that this doesn't work if a SVC opcode is part of an EXECUTE
723		 *  opcode. Since there is no way to find out the opcode size this
724		 *  is the best we can do...
725		 */
726		if ((opcode & 0xff00) == 0x0a00) {
727			/* SVC opcode */
728			scno = opcode & 0xff;
729		}
730		else {
731			/* SVC got executed by EXECUTE instruction */
732
733			/*
734			 *  Do instruction decoding of EXECUTE. If you really want to
735			 *  understand this, read the Principles of Operations.
736			 */
737			svc_addr = (void *) (opcode & 0xfff);
738
739			tmp = 0;
740			offset_reg = (opcode & 0x000f0000) >> 16;
741			if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
742				return -1;
743			svc_addr += tmp;
744
745			tmp = 0;
746			offset_reg = (opcode & 0x0000f000) >> 12;
747			if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
748				return -1;
749			svc_addr += tmp;
750
751			scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
752			if (errno)
753				return -1;
754# if defined(S390X)
755			scno >>= 48;
756# else
757			scno >>= 16;
758# endif
759			tmp = 0;
760			offset_reg = (opcode & 0x00f00000) >> 20;
761			if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
762				return -1;
763
764			scno = (scno | tmp) & 0xff;
765		}
766	}
767#elif defined(POWERPC)
768	if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
769		return -1;
770# ifdef POWERPC64
771	/* TODO: speed up strace by not doing this at every syscall.
772	 * We only need to do it after execve.
773	 */
774	int currpers;
775	long val;
776
777	/* Check for 64/32 bit mode. */
778	if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
779		return -1;
780	/* SF is bit 0 of MSR */
781	if (val < 0)
782		currpers = 0;
783	else
784		currpers = 1;
785	update_personality(tcp, currpers);
786# endif
787#elif defined(AVR32)
788	/* Read complete register set in one go. */
789	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
790		return -1;
791	scno = regs.r8;
792#elif defined(BFIN)
793	if (upeek(tcp, PT_ORIG_P0, &scno))
794		return -1;
795#elif defined(I386)
796	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
797		return -1;
798	scno = i386_regs.orig_eax;
799#elif defined(X86_64)
800	int currpers;
801	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
802		return -1;
803	scno = x86_64_regs.orig_rax;
804
805	/* Check CS register value. On x86-64 linux it is:
806	 *	0x33	for long mode (64 bit)
807	 *	0x23	for compatibility mode (32 bit)
808	 */
809	switch (x86_64_regs.cs) {
810		case 0x23: currpers = 1; break;
811		case 0x33: currpers = 0; break;
812		default:
813			fprintf(stderr, "Unknown value CS=0x%08X while "
814				 "detecting personality of process "
815				 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
816			currpers = current_personality;
817			break;
818	}
819# if 0
820	/* This version analyzes the opcode of a syscall instruction.
821	 * (int 0x80 on i386 vs. syscall on x86-64)
822	 * It works, but is too complicated.
823	 */
824	unsigned long val, rip, i;
825
826	rip = x86_64_regs.rip;
827
828	/* sizeof(syscall) == sizeof(int 0x80) == 2 */
829	rip -= 2;
830	errno = 0;
831
832	call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
833	if (errno)
834		fprintf(stderr, "ptrace_peektext failed: %s\n",
835				strerror(errno));
836	switch (call & 0xffff) {
837		/* x86-64: syscall = 0x0f 0x05 */
838		case 0x050f: currpers = 0; break;
839		/* i386: int 0x80 = 0xcd 0x80 */
840		case 0x80cd: currpers = 1; break;
841		default:
842			currpers = current_personality;
843			fprintf(stderr,
844				"Unknown syscall opcode (0x%04X) while "
845				"detecting personality of process "
846				"PID=%d\n", (int)call, tcp->pid);
847			break;
848	}
849# endif
850	update_personality(tcp, currpers);
851#elif defined(IA64)
852#	define IA64_PSR_IS	((long)1 << 34)
853	if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
854		ia32 = (psr & IA64_PSR_IS) != 0;
855	if (ia32) {
856		if (upeek(tcp, PT_R1, &scno) < 0)
857			return -1;
858	} else {
859		if (upeek(tcp, PT_R15, &scno) < 0)
860			return -1;
861	}
862#elif defined(ARM)
863	/* Read complete register set in one go. */
864	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
865		return -1;
866
867	/*
868	 * We only need to grab the syscall number on syscall entry.
869	 */
870	if (regs.ARM_ip == 0) {
871		/*
872		 * Note: we only deal with only 32-bit CPUs here.
873		 */
874		if (regs.ARM_cpsr & 0x20) {
875			/*
876			 * Get the Thumb-mode system call number
877			 */
878			scno = regs.ARM_r7;
879		} else {
880			/*
881			 * Get the ARM-mode system call number
882			 */
883			errno = 0;
884			scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
885			if (errno)
886				return -1;
887
888			/* Handle the EABI syscall convention.  We do not
889			   bother converting structures between the two
890			   ABIs, but basic functionality should work even
891			   if strace and the traced program have different
892			   ABIs.  */
893			if (scno == 0xef000000) {
894				scno = regs.ARM_r7;
895			} else {
896				if ((scno & 0x0ff00000) != 0x0f900000) {
897					fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
898						scno);
899					return -1;
900				}
901
902				/*
903				 * Fixup the syscall number
904				 */
905				scno &= 0x000fffff;
906			}
907		}
908		if (scno & 0x0f0000) {
909			/*
910			 * Handle ARM specific syscall
911			 */
912			update_personality(tcp, 1);
913			scno &= 0x0000ffff;
914		} else
915			update_personality(tcp, 0);
916
917	} else {
918		fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
919		tcp->flags |= TCB_INSYSCALL;
920	}
921#elif defined(M68K)
922	if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
923		return -1;
924#elif defined(LINUX_MIPSN32)
925	unsigned long long regs[38];
926
927	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
928		return -1;
929	a3 = regs[REG_A3];
930	r2 = regs[REG_V0];
931
932	scno = r2;
933	if (!SCNO_IN_RANGE(scno)) {
934		if (a3 == 0 || a3 == -1) {
935			if (debug_flag)
936				fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
937			return 0;
938		}
939	}
940#elif defined(MIPS)
941	if (upeek(tcp, REG_A3, &a3) < 0)
942		return -1;
943	if (upeek(tcp, REG_V0, &scno) < 0)
944		return -1;
945
946	if (!SCNO_IN_RANGE(scno)) {
947		if (a3 == 0 || a3 == -1) {
948			if (debug_flag)
949				fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
950			return 0;
951		}
952	}
953#elif defined(ALPHA)
954	if (upeek(tcp, REG_A3, &a3) < 0)
955		return -1;
956	if (upeek(tcp, REG_R0, &scno) < 0)
957		return -1;
958
959	/*
960	 * Do some sanity checks to figure out if it's
961	 * really a syscall entry
962	 */
963	if (!SCNO_IN_RANGE(scno)) {
964		if (a3 == 0 || a3 == -1) {
965			if (debug_flag)
966				fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
967			return 0;
968		}
969	}
970#elif defined(SPARC) || defined(SPARC64)
971	/* Everything we need is in the current register set. */
972	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
973		return -1;
974
975	/* Disassemble the syscall trap. */
976	/* Retrieve the syscall trap instruction. */
977	errno = 0;
978# if defined(SPARC64)
979	trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
980	trap >>= 32;
981# else
982	trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
983# endif
984	if (errno)
985		return -1;
986
987	/* Disassemble the trap to see what personality to use. */
988	switch (trap) {
989	case 0x91d02010:
990		/* Linux/SPARC syscall trap. */
991		update_personality(tcp, 0);
992		break;
993	case 0x91d0206d:
994		/* Linux/SPARC64 syscall trap. */
995		update_personality(tcp, 2);
996		break;
997	case 0x91d02000:
998		/* SunOS syscall trap. (pers 1) */
999		fprintf(stderr, "syscall: SunOS no support\n");
1000		return -1;
1001	case 0x91d02008:
1002		/* Solaris 2.x syscall trap. (per 2) */
1003		update_personality(tcp, 1);
1004		break;
1005	case 0x91d02009:
1006		/* NetBSD/FreeBSD syscall trap. */
1007		fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1008		return -1;
1009	case 0x91d02027:
1010		/* Solaris 2.x gettimeofday */
1011		update_personality(tcp, 1);
1012		break;
1013	default:
1014# if defined(SPARC64)
1015		fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
1016# else
1017		fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
1018# endif
1019		return -1;
1020	}
1021
1022	/* Extract the system call number from the registers. */
1023	if (trap == 0x91d02027)
1024		scno = 156;
1025	else
1026		scno = regs.u_regs[U_REG_G1];
1027	if (scno == 0) {
1028		scno = regs.u_regs[U_REG_O0];
1029		memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1030	}
1031#elif defined(HPPA)
1032	if (upeek(tcp, PT_GR20, &scno) < 0)
1033		return -1;
1034#elif defined(SH)
1035	/*
1036	 * In the new syscall ABI, the system call number is in R3.
1037	 */
1038	if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1039		return -1;
1040
1041	if (scno < 0) {
1042		/* Odd as it may seem, a glibc bug has been known to cause
1043		   glibc to issue bogus negative syscall numbers.  So for
1044		   our purposes, make strace print what it *should* have been */
1045		long correct_scno = (scno & 0xff);
1046		if (debug_flag)
1047			fprintf(stderr,
1048				"Detected glibc bug: bogus system call"
1049				" number = %ld, correcting to %ld\n",
1050				scno,
1051				correct_scno);
1052		scno = correct_scno;
1053	}
1054#elif defined(SH64)
1055	if (upeek(tcp, REG_SYSCALL, &scno) < 0)
1056		return -1;
1057	scno &= 0xFFFF;
1058#elif defined(CRISV10) || defined(CRISV32)
1059	if (upeek(tcp, 4*PT_R9, &scno) < 0)
1060		return -1;
1061#elif defined(TILE)
1062	if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1063		return -1;
1064#elif defined(MICROBLAZE)
1065	if (upeek(tcp, 0, &scno) < 0)
1066		return -1;
1067#endif
1068
1069#if defined(SH)
1070	/* new syscall ABI returns result in R0 */
1071	if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1072		return -1;
1073#elif defined(SH64)
1074	/* ABI defines result returned in r9 */
1075	if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1076		return -1;
1077#endif
1078
1079	tcp->scno = scno;
1080	return 1;
1081}
1082
1083/* Called at each syscall entry.
1084 * Returns:
1085 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1086 * 1: ok, continue in trace_syscall().
1087 * other: error, trace_syscall() should print error indicator
1088 *    ("????" etc) and bail out.
1089 */
1090static int
1091syscall_fixup_on_sysenter(struct tcb *tcp)
1092{
1093	/* A common case of "not a syscall entry" is post-execve SIGTRAP */
1094#if defined(I386)
1095	if (i386_regs.eax != -ENOSYS) {
1096		if (debug_flag)
1097			fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1098		return 0;
1099	}
1100#elif defined(X86_64)
1101	{
1102		long rax = x86_64_regs.rax;
1103		if (current_personality == 1)
1104			rax = (int)rax; /* sign extend from 32 bits */
1105		if (rax != -ENOSYS) {
1106			if (debug_flag)
1107				fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1108			return 0;
1109		}
1110	}
1111#elif defined(S390) || defined(S390X)
1112	/* TODO: we already fetched PT_GPR2 in get_scno
1113	 * and stored it in syscall_mode, reuse it here
1114	 * instead of re-fetching?
1115	 */
1116	if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1117		return -1;
1118	if (syscall_mode != -ENOSYS)
1119		syscall_mode = tcp->scno;
1120	if (gpr2 != syscall_mode) {
1121		if (debug_flag)
1122			fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
1123		return 0;
1124	}
1125#elif defined(M68K)
1126	/* TODO? Eliminate upeek's in arches below like we did in x86 */
1127	if (upeek(tcp, 4*PT_D0, &d0) < 0)
1128		return -1;
1129	if (d0 != -ENOSYS) {
1130		if (debug_flag)
1131			fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
1132		return 0;
1133	}
1134#elif defined(IA64)
1135	if (upeek(tcp, PT_R10, &r10) < 0)
1136		return -1;
1137	if (upeek(tcp, PT_R8, &r8) < 0)
1138		return -1;
1139	if (ia32 && r8 != -ENOSYS) {
1140		if (debug_flag)
1141			fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
1142		return 0;
1143	}
1144#elif defined(CRISV10) || defined(CRISV32)
1145	if (upeek(tcp, 4*PT_R10, &r10) < 0)
1146		return -1;
1147	if (r10 != -ENOSYS) {
1148		if (debug_flag)
1149			fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
1150		return 0;
1151	}
1152#elif defined(MICROBLAZE)
1153	if (upeek(tcp, 3 * 4, &r3) < 0)
1154		return -1;
1155	if (r3 != -ENOSYS) {
1156		if (debug_flag)
1157			fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
1158		return 0;
1159	}
1160#endif
1161	return 1;
1162}
1163
1164static void
1165internal_fork(struct tcb *tcp)
1166{
1167#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1168# define ARG_FLAGS	1
1169#else
1170# define ARG_FLAGS	0
1171#endif
1172#ifndef CLONE_UNTRACED
1173# define CLONE_UNTRACED	0x00800000
1174#endif
1175	if ((ptrace_setoptions
1176	    & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1177	   == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1178		return;
1179
1180	if (!followfork)
1181		return;
1182
1183	if (entering(tcp)) {
1184		/*
1185		 * We won't see the new child if clone is called with
1186		 * CLONE_UNTRACED, so we keep the same logic with that option
1187		 * and don't trace it.
1188		 */
1189		if ((sysent[tcp->scno].sys_func == sys_clone) &&
1190		    (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1191			return;
1192		setbpt(tcp);
1193	} else {
1194		if (tcp->flags & TCB_BPTSET)
1195			clearbpt(tcp);
1196	}
1197}
1198
1199#if defined(TCB_WAITEXECVE)
1200static void
1201internal_exec(struct tcb *tcp)
1202{
1203	/* Maybe we have post-execve SIGTRAP suppressed? */
1204	if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1205		return; /* yes, no need to do anything */
1206
1207	if (exiting(tcp) && syserror(tcp))
1208		/* Error in execve, no post-execve SIGTRAP expected */
1209		tcp->flags &= ~TCB_WAITEXECVE;
1210	else
1211		tcp->flags |= TCB_WAITEXECVE;
1212}
1213#endif
1214
1215static void
1216internal_syscall(struct tcb *tcp)
1217{
1218	/*
1219	 * We must always trace a few critical system calls in order to
1220	 * correctly support following forks in the presence of tracing
1221	 * qualifiers.
1222	 */
1223	int (*func)();
1224
1225	if (!SCNO_IN_RANGE(tcp->scno))
1226		return;
1227
1228	func = sysent[tcp->scno].sys_func;
1229
1230	if (   sys_fork == func
1231	    || sys_vfork == func
1232	    || sys_clone == func
1233	   ) {
1234		internal_fork(tcp);
1235		return;
1236	}
1237
1238#if defined(TCB_WAITEXECVE)
1239	if (   sys_execve == func
1240# if defined(SPARC) || defined(SPARC64)
1241	    || sys_execv == func
1242# endif
1243	   ) {
1244		internal_exec(tcp);
1245		return;
1246	}
1247#endif
1248}
1249
1250static int
1251syscall_enter(struct tcb *tcp)
1252{
1253	int i, nargs;
1254
1255	if (SCNO_IN_RANGE(tcp->scno))
1256		nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
1257	else
1258		nargs = tcp->u_nargs = MAX_ARGS;
1259
1260#if defined(S390) || defined(S390X)
1261	for (i = 0; i < nargs; ++i)
1262		if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1263			return -1;
1264#elif defined(ALPHA)
1265	for (i = 0; i < nargs; ++i)
1266		if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1267			return -1;
1268#elif defined(IA64)
1269	if (!ia32) {
1270		unsigned long *out0, cfm, sof, sol;
1271		long rbs_end;
1272		/* be backwards compatible with kernel < 2.4.4... */
1273#		ifndef PT_RBS_END
1274#		  define PT_RBS_END	PT_AR_BSP
1275#		endif
1276
1277		if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1278			return -1;
1279		if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
1280			return -1;
1281
1282		sof = (cfm >> 0) & 0x7f;
1283		sol = (cfm >> 7) & 0x7f;
1284		out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1285
1286		for (i = 0; i < nargs; ++i) {
1287			if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1288				   sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1289				return -1;
1290		}
1291	} else {
1292		static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1293						      PT_R9  /* ECX = out1 */,
1294						      PT_R10 /* EDX = out2 */,
1295						      PT_R14 /* ESI = out3 */,
1296						      PT_R15 /* EDI = out4 */,
1297						      PT_R13 /* EBP = out5 */};
1298
1299		for (i = 0; i < nargs; ++i) {
1300			if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1301				return -1;
1302			/* truncate away IVE sign-extension */
1303			tcp->u_arg[i] &= 0xffffffff;
1304		}
1305	}
1306#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
1307	/* N32 and N64 both use up to six registers.  */
1308	unsigned long long regs[38];
1309
1310	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1311		return -1;
1312
1313	for (i = 0; i < nargs; ++i) {
1314		tcp->u_arg[i] = regs[REG_A0 + i];
1315# if defined(LINUX_MIPSN32)
1316		tcp->ext_arg[i] = regs[REG_A0 + i];
1317# endif
1318	}
1319#elif defined(MIPS)
1320	if (nargs > 4) {
1321		long sp;
1322
1323		if (upeek(tcp, REG_SP, &sp) < 0)
1324			return -1;
1325		for (i = 0; i < 4; ++i)
1326			if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1327				return -1;
1328		umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
1329		       (char *)(tcp->u_arg + 4));
1330	} else {
1331		for (i = 0; i < nargs; ++i)
1332			if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1333				return -1;
1334	}
1335#elif defined(POWERPC)
1336# ifndef PT_ORIG_R3
1337#  define PT_ORIG_R3 34
1338# endif
1339	for (i = 0; i < nargs; ++i) {
1340		if (upeek(tcp, (i==0) ?
1341			(sizeof(unsigned long) * PT_ORIG_R3) :
1342			((i+PT_R3) * sizeof(unsigned long)),
1343				&tcp->u_arg[i]) < 0)
1344			return -1;
1345	}
1346#elif defined(SPARC) || defined(SPARC64)
1347	for (i = 0; i < nargs; ++i)
1348		tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
1349#elif defined(HPPA)
1350	for (i = 0; i < nargs; ++i)
1351		if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1352			return -1;
1353#elif defined(ARM)
1354	for (i = 0; i < nargs; ++i)
1355		tcp->u_arg[i] = regs.uregs[i];
1356#elif defined(AVR32)
1357	(void)i;
1358	(void)nargs;
1359	tcp->u_arg[0] = regs.r12;
1360	tcp->u_arg[1] = regs.r11;
1361	tcp->u_arg[2] = regs.r10;
1362	tcp->u_arg[3] = regs.r9;
1363	tcp->u_arg[4] = regs.r5;
1364	tcp->u_arg[5] = regs.r3;
1365#elif defined(BFIN)
1366	static const int argreg[MAX_ARGS] = { PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5 };
1367
1368	for (i = 0; i < nargs; ++i)
1369		if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1370			return -1;
1371#elif defined(SH)
1372	static const int syscall_regs[MAX_ARGS] = {
1373		4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1374		4 * (REG_REG0+7), 4 * (REG_REG0  ), 4 * (REG_REG0+1)
1375	};
1376
1377	for (i = 0; i < nargs; ++i)
1378		if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
1379			return -1;
1380#elif defined(SH64)
1381	int i;
1382	/* Registers used by SH5 Linux system calls for parameters */
1383	static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
1384
1385	for (i = 0; i < nargs; ++i)
1386		if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1387			return -1;
1388#elif defined(X86_64)
1389	(void)i;
1390	(void)nargs;
1391	if (current_personality == 0) { /* x86-64 ABI */
1392		tcp->u_arg[0] = x86_64_regs.rdi;
1393		tcp->u_arg[1] = x86_64_regs.rsi;
1394		tcp->u_arg[2] = x86_64_regs.rdx;
1395		tcp->u_arg[3] = x86_64_regs.r10;
1396		tcp->u_arg[4] = x86_64_regs.r8;
1397		tcp->u_arg[5] = x86_64_regs.r9;
1398	} else { /* i386 ABI */
1399		/* Sign-extend lower 32 bits */
1400		tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1401		tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1402		tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1403		tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1404		tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1405		tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1406	}
1407#elif defined(MICROBLAZE)
1408	for (i = 0; i < nargs; ++i)
1409		if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1410			return -1;
1411#elif defined(CRISV10) || defined(CRISV32)
1412	static const int crisregs[MAX_ARGS] = {
1413		4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
1414		4*PT_R13     , 4*PT_MOF, 4*PT_SRP
1415	};
1416
1417	for (i = 0; i < nargs; ++i)
1418		if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1419			return -1;
1420#elif defined(TILE)
1421	for (i = 0; i < nargs; ++i)
1422		if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
1423			return -1;
1424#elif defined(M68K)
1425	for (i = 0; i < nargs; ++i)
1426		if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1427			return -1;
1428#elif defined(I386)
1429	(void)i;
1430	(void)nargs;
1431	tcp->u_arg[0] = i386_regs.ebx;
1432	tcp->u_arg[1] = i386_regs.ecx;
1433	tcp->u_arg[2] = i386_regs.edx;
1434	tcp->u_arg[3] = i386_regs.esi;
1435	tcp->u_arg[4] = i386_regs.edi;
1436	tcp->u_arg[5] = i386_regs.ebp;
1437#else /* Other architecture (32bits specific) */
1438	for (i = 0; i < nargs; ++i)
1439		if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1440			return -1;
1441#endif
1442	return 1;
1443}
1444
1445static int
1446trace_syscall_entering(struct tcb *tcp)
1447{
1448	int res, scno_good;
1449
1450#if defined TCB_WAITEXECVE
1451	if (tcp->flags & TCB_WAITEXECVE) {
1452		/* This is the post-execve SIGTRAP. */
1453		tcp->flags &= ~TCB_WAITEXECVE;
1454		return 0;
1455	}
1456#endif
1457
1458	scno_good = res = get_scno(tcp);
1459	if (res == 0)
1460		return res;
1461	if (res == 1)
1462		res = syscall_fixup_on_sysenter(tcp);
1463	if (res == 0)
1464		return res;
1465	if (res == 1)
1466		res = syscall_enter(tcp);
1467	if (res == 0)
1468		return res;
1469
1470	if (res != 1) {
1471		printleader(tcp);
1472		tcp->flags &= ~TCB_REPRINT;
1473		if (scno_good != 1)
1474			tprints("????" /* anti-trigraph gap */ "(");
1475		else if (!SCNO_IN_RANGE(tcp->scno))
1476			tprintf("syscall_%lu(", tcp->scno);
1477		else
1478			tprintf("%s(", sysent[tcp->scno].sys_name);
1479		/*
1480		 * " <unavailable>" will be added later by the code which
1481		 * detects ptrace errors.
1482		 */
1483		goto ret;
1484	}
1485
1486#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1487	while (SCNO_IN_RANGE(tcp->scno)) {
1488# ifdef SYS_socket_subcall
1489		if (sysent[tcp->scno].sys_func == sys_socketcall) {
1490			decode_socket_subcall(tcp);
1491			break;
1492		}
1493# endif
1494# ifdef SYS_ipc_subcall
1495		if (sysent[tcp->scno].sys_func == sys_ipc) {
1496			decode_ipc_subcall(tcp);
1497			break;
1498		}
1499# endif
1500		break;
1501	}
1502#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1503
1504	internal_syscall(tcp);
1505
1506	if ((SCNO_IN_RANGE(tcp->scno) &&
1507	     !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1508	    (tracing_paths && !pathtrace_match(tcp))) {
1509		tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1510		return 0;
1511	}
1512
1513	tcp->flags &= ~TCB_FILTERED;
1514
1515	if (cflag == CFLAG_ONLY_STATS) {
1516		res = 0;
1517		goto ret;
1518	}
1519
1520	printleader(tcp);
1521	tcp->flags &= ~TCB_REPRINT;
1522	if (!SCNO_IN_RANGE(tcp->scno))
1523		tprintf("syscall_%lu(", tcp->scno);
1524	else
1525		tprintf("%s(", sysent[tcp->scno].sys_name);
1526	if (!SCNO_IN_RANGE(tcp->scno) ||
1527	    ((qual_flags[tcp->scno] & QUAL_RAW) &&
1528	     sysent[tcp->scno].sys_func != sys_exit))
1529		res = printargs(tcp);
1530	else
1531		res = (*sysent[tcp->scno].sys_func)(tcp);
1532
1533	if (fflush(tcp->outf) == EOF)
1534		return -1;
1535 ret:
1536	tcp->flags |= TCB_INSYSCALL;
1537	/* Measure the entrance time as late as possible to avoid errors. */
1538	if (Tflag || cflag)
1539		gettimeofday(&tcp->etime, NULL);
1540	return res;
1541}
1542
1543/* Returns:
1544 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1545 * 1: ok, continue in trace_syscall().
1546 * other: error, trace_syscall() should print error indicator
1547 *    ("????" etc) and bail out.
1548 */
1549static int
1550get_syscall_result(struct tcb *tcp)
1551{
1552#if defined(S390) || defined(S390X)
1553	if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1554		return -1;
1555#elif defined(POWERPC)
1556# define SO_MASK 0x10000000
1557	{
1558		long flags;
1559		if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1560			return -1;
1561		if (upeek(tcp, sizeof(unsigned long)*PT_R3, &result) < 0)
1562			return -1;
1563		if (flags & SO_MASK)
1564			result = -result;
1565	}
1566#elif defined(AVR32)
1567	/* Read complete register set in one go. */
1568	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
1569		return -1;
1570#elif defined(BFIN)
1571	if (upeek(tcp, PT_R0, &r0) < 0)
1572		return -1;
1573#elif defined(I386)
1574	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &i386_regs) < 0)
1575		return -1;
1576#elif defined(X86_64)
1577	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &x86_64_regs) < 0)
1578		return -1;
1579#elif defined(IA64)
1580#	define IA64_PSR_IS	((long)1 << 34)
1581	if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1582		ia32 = (psr & IA64_PSR_IS) != 0;
1583	if (upeek(tcp, PT_R8, &r8) < 0)
1584		return -1;
1585	if (upeek(tcp, PT_R10, &r10) < 0)
1586		return -1;
1587#elif defined(ARM)
1588	/* Read complete register set in one go. */
1589	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1590		return -1;
1591#elif defined(M68K)
1592	if (upeek(tcp, 4*PT_D0, &d0) < 0)
1593		return -1;
1594#elif defined(LINUX_MIPSN32)
1595	unsigned long long regs[38];
1596
1597	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1598		return -1;
1599	a3 = regs[REG_A3];
1600	r2 = regs[REG_V0];
1601#elif defined(MIPS)
1602	if (upeek(tcp, REG_A3, &a3) < 0)
1603		return -1;
1604	if (upeek(tcp, REG_V0, &r2) < 0)
1605		return -1;
1606#elif defined(ALPHA)
1607	if (upeek(tcp, REG_A3, &a3) < 0)
1608		return -1;
1609	if (upeek(tcp, REG_R0, &r0) < 0)
1610		return -1;
1611#elif defined(SPARC) || defined(SPARC64)
1612	/* Everything we need is in the current register set. */
1613	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1614		return -1;
1615#elif defined(HPPA)
1616	if (upeek(tcp, PT_GR28, &r28) < 0)
1617		return -1;
1618#elif defined(SH)
1619#elif defined(SH64)
1620#elif defined(CRISV10) || defined(CRISV32)
1621	if (upeek(tcp, 4*PT_R10, &r10) < 0)
1622		return -1;
1623#elif defined(TILE)
1624#elif defined(MICROBLAZE)
1625	if (upeek(tcp, 3 * 4, &r3) < 0)
1626		return -1;
1627#endif
1628
1629#if defined(SH)
1630	/* new syscall ABI returns result in R0 */
1631	if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1632		return -1;
1633#elif defined(SH64)
1634	/* ABI defines result returned in r9 */
1635	if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1636		return -1;
1637#endif
1638
1639	return 1;
1640}
1641
1642/* Called at each syscall exit.
1643 * Returns:
1644 * 0: "ignore this ptrace stop", bail out of trace_syscall() silently.
1645 * 1: ok, continue in trace_syscall().
1646 * other: error, trace_syscall() should print error indicator
1647 *    ("????" etc) and bail out.
1648 */
1649static int
1650syscall_fixup_on_sysexit(struct tcb *tcp)
1651{
1652#if defined(S390) || defined(S390X)
1653	if (syscall_mode != -ENOSYS)
1654		syscall_mode = tcp->scno;
1655	if ((tcp->flags & TCB_WAITEXECVE)
1656		 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1657		/*
1658		 * Return from execve.
1659		 * Fake a return value of zero.  We leave the TCB_WAITEXECVE
1660		 * flag set for the post-execve SIGTRAP to see and reset.
1661		 */
1662		gpr2 = 0;
1663	}
1664#endif
1665	return 1;
1666}
1667
1668/*
1669 * Check the syscall return value register value for whether it is
1670 * a negated errno code indicating an error, or a success return value.
1671 */
1672static inline int
1673is_negated_errno(unsigned long int val)
1674{
1675	unsigned long int max = -(long int) nerrnos;
1676#if SUPPORTED_PERSONALITIES > 1
1677	if (current_wordsize < sizeof(val)) {
1678		val = (unsigned int) val;
1679		max = (unsigned int) max;
1680	}
1681#endif
1682	return val > max;
1683}
1684
1685static int
1686get_error(struct tcb *tcp)
1687{
1688	int u_error = 0;
1689	int check_errno = 1;
1690	if (SCNO_IN_RANGE(tcp->scno) &&
1691	    sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1692		check_errno = 0;
1693	}
1694#if defined(S390) || defined(S390X)
1695	if (check_errno && is_negated_errno(gpr2)) {
1696		tcp->u_rval = -1;
1697		u_error = -gpr2;
1698	}
1699	else {
1700		tcp->u_rval = gpr2;
1701	}
1702#elif defined(I386)
1703	if (check_errno && is_negated_errno(i386_regs.eax)) {
1704		tcp->u_rval = -1;
1705		u_error = -i386_regs.eax;
1706	}
1707	else {
1708		tcp->u_rval = i386_regs.eax;
1709	}
1710#elif defined(X86_64)
1711	if (check_errno && is_negated_errno(x86_64_regs.rax)) {
1712		tcp->u_rval = -1;
1713		u_error = -x86_64_regs.rax;
1714	}
1715	else {
1716		tcp->u_rval = x86_64_regs.rax;
1717	}
1718#elif defined(IA64)
1719	if (ia32) {
1720		int err;
1721
1722		err = (int)r8;
1723		if (check_errno && is_negated_errno(err)) {
1724			tcp->u_rval = -1;
1725			u_error = -err;
1726		}
1727		else {
1728			tcp->u_rval = err;
1729		}
1730	} else {
1731		if (check_errno && r10) {
1732			tcp->u_rval = -1;
1733			u_error = r8;
1734		} else {
1735			tcp->u_rval = r8;
1736		}
1737	}
1738#elif defined(MIPS)
1739	if (check_errno && a3) {
1740		tcp->u_rval = -1;
1741		u_error = r2;
1742	} else {
1743		tcp->u_rval = r2;
1744	}
1745#elif defined(POWERPC)
1746	if (check_errno && is_negated_errno(result)) {
1747		tcp->u_rval = -1;
1748		u_error = -result;
1749	}
1750	else {
1751		tcp->u_rval = result;
1752	}
1753#elif defined(M68K)
1754	if (check_errno && is_negated_errno(d0)) {
1755		tcp->u_rval = -1;
1756		u_error = -d0;
1757	}
1758	else {
1759		tcp->u_rval = d0;
1760	}
1761#elif defined(ARM)
1762	if (check_errno && is_negated_errno(regs.ARM_r0)) {
1763		tcp->u_rval = -1;
1764		u_error = -regs.ARM_r0;
1765	}
1766	else {
1767		tcp->u_rval = regs.ARM_r0;
1768	}
1769#elif defined(AVR32)
1770	if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1771		tcp->u_rval = -1;
1772		u_error = -regs.r12;
1773	}
1774	else {
1775		tcp->u_rval = regs.r12;
1776	}
1777#elif defined(BFIN)
1778	if (check_errno && is_negated_errno(r0)) {
1779		tcp->u_rval = -1;
1780		u_error = -r0;
1781	} else {
1782		tcp->u_rval = r0;
1783	}
1784#elif defined(ALPHA)
1785	if (check_errno && a3) {
1786		tcp->u_rval = -1;
1787		u_error = r0;
1788	}
1789	else {
1790		tcp->u_rval = r0;
1791	}
1792#elif defined(SPARC)
1793	if (check_errno && regs.psr & PSR_C) {
1794		tcp->u_rval = -1;
1795		u_error = regs.u_regs[U_REG_O0];
1796	}
1797	else {
1798		tcp->u_rval = regs.u_regs[U_REG_O0];
1799	}
1800#elif defined(SPARC64)
1801	if (check_errno && regs.tstate & 0x1100000000UL) {
1802		tcp->u_rval = -1;
1803		u_error = regs.u_regs[U_REG_O0];
1804	}
1805	else {
1806		tcp->u_rval = regs.u_regs[U_REG_O0];
1807	}
1808#elif defined(HPPA)
1809	if (check_errno && is_negated_errno(r28)) {
1810		tcp->u_rval = -1;
1811		u_error = -r28;
1812	}
1813	else {
1814		tcp->u_rval = r28;
1815	}
1816#elif defined(SH)
1817	if (check_errno && is_negated_errno(r0)) {
1818		tcp->u_rval = -1;
1819		u_error = -r0;
1820	}
1821	else {
1822		tcp->u_rval = r0;
1823	}
1824#elif defined(SH64)
1825	if (check_errno && is_negated_errno(r9)) {
1826		tcp->u_rval = -1;
1827		u_error = -r9;
1828	}
1829	else {
1830		tcp->u_rval = r9;
1831	}
1832#elif defined(CRISV10) || defined(CRISV32)
1833	if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
1834		tcp->u_rval = -1;
1835		u_error = -r10;
1836	}
1837	else {
1838		tcp->u_rval = r10;
1839	}
1840#elif defined(TILE)
1841	long rval;
1842	if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1843		return -1;
1844	if (check_errno && rval < 0 && rval > -nerrnos) {
1845		tcp->u_rval = -1;
1846		u_error = -rval;
1847	}
1848	else {
1849		tcp->u_rval = rval;
1850	}
1851#elif defined(MICROBLAZE)
1852	if (check_errno && is_negated_errno(r3)) {
1853		tcp->u_rval = -1;
1854		u_error = -r3;
1855	}
1856	else {
1857		tcp->u_rval = r3;
1858	}
1859#endif
1860	tcp->u_error = u_error;
1861	return 1;
1862}
1863
1864static void
1865dumpio(struct tcb *tcp)
1866{
1867	if (syserror(tcp))
1868		return;
1869	if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
1870		return;
1871	if (!SCNO_IN_RANGE(tcp->scno))
1872		return;
1873	if (sysent[tcp->scno].sys_func == printargs)
1874		return;
1875	if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
1876		if (sysent[tcp->scno].sys_func == sys_read ||
1877		    sysent[tcp->scno].sys_func == sys_pread ||
1878		    sysent[tcp->scno].sys_func == sys_recv ||
1879		    sysent[tcp->scno].sys_func == sys_recvfrom)
1880			dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
1881		else if (sysent[tcp->scno].sys_func == sys_readv)
1882			dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1883		return;
1884	}
1885	if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
1886		if (sysent[tcp->scno].sys_func == sys_write ||
1887		    sysent[tcp->scno].sys_func == sys_pwrite ||
1888		    sysent[tcp->scno].sys_func == sys_send ||
1889		    sysent[tcp->scno].sys_func == sys_sendto)
1890			dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
1891		else if (sysent[tcp->scno].sys_func == sys_writev)
1892			dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
1893		return;
1894	}
1895}
1896
1897static int
1898trace_syscall_exiting(struct tcb *tcp)
1899{
1900	int sys_res;
1901	struct timeval tv;
1902	int res;
1903	long u_error;
1904
1905	/* Measure the exit time as early as possible to avoid errors. */
1906	if (Tflag || cflag)
1907		gettimeofday(&tv, NULL);
1908
1909#if SUPPORTED_PERSONALITIES > 1
1910	update_personality(tcp, tcp->currpers);
1911#endif
1912	res = get_syscall_result(tcp);
1913	if (res == 0)
1914		return res;
1915	if (res == 1)
1916		res = syscall_fixup_on_sysexit(tcp);
1917	if (res == 0)
1918		return res;
1919	if (res == 1)
1920		res = get_error(tcp);
1921	if (res == 0)
1922		return res;
1923	if (res == 1)
1924		internal_syscall(tcp);
1925
1926	if (res == 1 && filtered(tcp)) {
1927		goto ret;
1928	}
1929
1930	/* TODO: TCB_REPRINT is probably not necessary:
1931	 * we can determine whether reprinting is needed
1932	 * by examining printing_tcp. Something like:
1933	 * if not in -ff mode, and printing_tcp != tcp,
1934	 * then the log is not currenlty ends with *our*
1935	 * syscall entry output, but with something else,
1936	 * and we need to reprint.
1937	 * If we'd implement this, printing_tcp = tcp
1938	 * assignments in code below can be made more logical.
1939	 */
1940
1941	if (tcp->flags & TCB_REPRINT) {
1942		printleader(tcp);
1943		if (!SCNO_IN_RANGE(tcp->scno))
1944			tprintf("<... syscall_%lu resumed> ", tcp->scno);
1945		else
1946			tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
1947	}
1948
1949	if (cflag) {
1950		struct timeval t = tv;
1951		count_syscall(tcp, &t);
1952		if (cflag == CFLAG_ONLY_STATS) {
1953			goto ret;
1954		}
1955	}
1956
1957	if (res != 1) {
1958		printing_tcp = tcp;
1959		tprints(") ");
1960		tabto();
1961		tprints("= ? <unavailable>\n");
1962		line_ended();
1963		tcp->flags &= ~TCB_INSYSCALL;
1964		return res;
1965	}
1966
1967	if (!SCNO_IN_RANGE(tcp->scno)
1968	    || (qual_flags[tcp->scno] & QUAL_RAW)) {
1969		printing_tcp = tcp;
1970		sys_res = printargs(tcp);
1971	} else {
1972	/* FIXME: not_failing_only (IOW, option -z) is broken:
1973	 * failure of syscall is known only after syscall return.
1974	 * Thus we end up with something like this on, say, ENOENT:
1975	 *     open("doesnt_exist", O_RDONLY <unfinished ...>
1976	 *     {next syscall decode}
1977	 * whereas the intended result is that open(...) line
1978	 * is not shown at all.
1979	 */
1980		if (not_failing_only && tcp->u_error)
1981			goto ret;	/* ignore failed syscalls */
1982		printing_tcp = tcp;
1983		sys_res = (*sysent[tcp->scno].sys_func)(tcp);
1984	}
1985
1986	tprints(") ");
1987	tabto();
1988	u_error = tcp->u_error;
1989	if (!SCNO_IN_RANGE(tcp->scno) ||
1990	    qual_flags[tcp->scno] & QUAL_RAW) {
1991		if (u_error)
1992			tprintf("= -1 (errno %ld)", u_error);
1993		else
1994			tprintf("= %#lx", tcp->u_rval);
1995	}
1996	else if (!(sys_res & RVAL_NONE) && u_error) {
1997		switch (u_error) {
1998		/* Blocked signals do not interrupt any syscalls.
1999		 * In this case syscalls don't return ERESTARTfoo codes.
2000		 *
2001		 * Deadly signals set to SIG_DFL interrupt syscalls
2002		 * and kill the process regardless of which of the codes below
2003		 * is returned by the interrupted syscall.
2004		 * In some cases, kernel forces a kernel-generated deadly
2005		 * signal to be unblocked and set to SIG_DFL (and thus cause
2006		 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2007		 * or SIGILL. (The alternative is to leave process spinning
2008		 * forever on the faulty instruction - not useful).
2009		 *
2010		 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2011		 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2012		 * but kernel will always restart them.
2013		 */
2014		case ERESTARTSYS:
2015			/* Most common type of signal-interrupted syscall exit code.
2016			 * The system call will be restarted with the same arguments
2017			 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2018			 */
2019			tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
2020			break;
2021		case ERESTARTNOINTR:
2022			/* Rare. For example, fork() returns this if interrupted.
2023			 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2024			 */
2025			tprints("= ? ERESTARTNOINTR (To be restarted)");
2026			break;
2027		case ERESTARTNOHAND:
2028			/* pause(), rt_sigsuspend() etc use this code.
2029			 * SA_RESTART is ignored (assumed not set):
2030			 * syscall won't restart (will return EINTR instead)
2031			 * even after signal with SA_RESTART set.
2032			 * However, after SIG_IGN or SIG_DFL signal it will.
2033			 */
2034			tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
2035			break;
2036		case ERESTART_RESTARTBLOCK:
2037			/* Syscalls like nanosleep(), poll() which can't be
2038			 * restarted with their original arguments use this
2039			 * code. Kernel will execute restart_syscall() instead,
2040			 * which changes arguments before restarting syscall.
2041			 * SA_RESTART is ignored (assumed not set) similarly
2042			 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2043			 * since restart data is saved in "restart block"
2044			 * in task struct, and if signal handler uses a syscall
2045			 * which in turn saves another such restart block,
2046			 * old data is lost and restart becomes impossible)
2047			 */
2048			tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
2049			break;
2050		default:
2051			if (u_error < 0)
2052				tprintf("= -1 E??? (errno %ld)", u_error);
2053			else if (u_error < nerrnos)
2054				tprintf("= -1 %s (%s)", errnoent[u_error],
2055					strerror(u_error));
2056			else
2057				tprintf("= -1 ERRNO_%ld (%s)", u_error,
2058					strerror(u_error));
2059			break;
2060		}
2061		if ((sys_res & RVAL_STR) && tcp->auxstr)
2062			tprintf(" (%s)", tcp->auxstr);
2063	}
2064	else {
2065		if (sys_res & RVAL_NONE)
2066			tprints("= ?");
2067		else {
2068			switch (sys_res & RVAL_MASK) {
2069			case RVAL_HEX:
2070				tprintf("= %#lx", tcp->u_rval);
2071				break;
2072			case RVAL_OCTAL:
2073				tprintf("= %#lo", tcp->u_rval);
2074				break;
2075			case RVAL_UDECIMAL:
2076				tprintf("= %lu", tcp->u_rval);
2077				break;
2078			case RVAL_DECIMAL:
2079				tprintf("= %ld", tcp->u_rval);
2080				break;
2081			default:
2082				fprintf(stderr,
2083					"invalid rval format\n");
2084				break;
2085			}
2086		}
2087		if ((sys_res & RVAL_STR) && tcp->auxstr)
2088			tprintf(" (%s)", tcp->auxstr);
2089	}
2090	if (Tflag) {
2091		tv_sub(&tv, &tv, &tcp->etime);
2092		tprintf(" <%ld.%06ld>",
2093			(long) tv.tv_sec, (long) tv.tv_usec);
2094	}
2095	tprints("\n");
2096	dumpio(tcp);
2097	line_ended();
2098
2099 ret:
2100	tcp->flags &= ~TCB_INSYSCALL;
2101	return 0;
2102}
2103
2104int
2105trace_syscall(struct tcb *tcp)
2106{
2107	return exiting(tcp) ?
2108		trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2109}
2110