syscall.c revision 4bdb6bb7346de8577402d73e71616e8632269261
123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)/*
223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) *                     Linux for s390 port by D.J. Barrow
823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) *                    <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * All rights reserved.
1023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) *
1123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
1223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * modification, are permitted provided that the following conditions
1323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * are met:
1423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
1583750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch *    notice, this list of conditions and the following disclaimer.
1623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
1723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
1823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
1923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * 3. The name of the author may not be used to endorse or promote products
2023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) *    derived from this software without specific prior written permission.
2123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) *
2223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) */
3323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
3423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#include "defs.h"
3523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#include <sys/user.h>
3623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#include <sys/param.h>
3723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
3823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#ifdef HAVE_SYS_REG_H
3923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# include <sys/reg.h>
4023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# ifndef PTRACE_PEEKUSR
4123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#  define PTRACE_PEEKUSR PTRACE_PEEKUSER
4223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# endif
4323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#elif defined(HAVE_LINUX_PTRACE_H)
4423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# undef PTRACE_SYSCALL
4523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# ifdef HAVE_STRUCT_IA64_FPREG
4623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#  define ia64_fpreg XXX_ia64_fpreg
4723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# endif
4823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
4923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#  define pt_all_user_regs XXX_pt_all_user_regs
5023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# endif
5123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# include <linux/ptrace.h>
5223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# undef ia64_fpreg
5323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# undef pt_all_user_regs
5423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
55e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
5623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#if defined(SPARC64)
5723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# undef PTRACE_GETREGS
5823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# define PTRACE_GETREGS PTRACE_GETREGS64
59e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch# undef PTRACE_SETREGS
6023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# define PTRACE_SETREGS PTRACE_SETREGS64
6123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
6223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
6323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#if defined(IA64)
6423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# include <asm/ptrace_offsets.h>
6523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# include <asm/rse.h>
6623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
6723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
6823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#if defined(AARCH64)
6923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# include <asm/ptrace.h>
7023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# include <sys/uio.h>
7123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# include <elf.h>
7223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
7323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
7423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#if defined(TILE)
7523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# ifndef PT_FLAGS_COMPAT
7623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#  define PT_FLAGS_COMPAT 0x10000  /* from Linux 3.8 on */
7723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# endif
7823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
7923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
8023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#ifndef ERESTARTSYS
8123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# define ERESTARTSYS	512
8223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
8323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#ifndef ERESTARTNOINTR
8423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# define ERESTARTNOINTR	513
8523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
8623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#ifndef ERESTARTNOHAND
8723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# define ERESTARTNOHAND	514	/* restart if no handler */
8823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
8923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#ifndef ERESTART_RESTARTBLOCK
9023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# define ERESTART_RESTARTBLOCK 516	/* restart by calling sys_restart_syscall */
9123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
9223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
9323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#ifndef NSIG
9423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# warning: NSIG is not defined, using 32
9523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# define NSIG 32
9623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
9723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#ifdef ARM
9823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)/* Ugh. Is this really correct? ARM has no RT signals?! */
9923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# undef NSIG
10023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# define NSIG 32
10123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
10223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
10323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#include "syscall.h"
10423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
10523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)/* Define these shorthand notations to simplify the syscallent files. */
10623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#define TD TRACE_DESC
10723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#define TF TRACE_FILE
10823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#define TI TRACE_IPC
10923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#define TN TRACE_NETWORK
11023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#define TP TRACE_PROCESS
11123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#define TS TRACE_SIGNAL
11223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#define TM TRACE_MEMORY
1137757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define NF SYSCALL_NEVER_FAILS
11423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#define MA MAX_ARGS
11523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
11623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static const struct sysent sysent0[] = {
11723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#include "syscallent.h"
11823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)};
11923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
12023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#if SUPPORTED_PERSONALITIES >= 2
12123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static const struct sysent sysent1[] = {
12223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# include "syscallent1.h"
12323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)};
12423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
1257757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
12623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#if SUPPORTED_PERSONALITIES >= 3
12723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static const struct sysent sysent2[] = {
12823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# include "syscallent2.h"
12923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)};
13023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
13123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
13223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)/* Now undef them since short defines cause wicked namespace pollution. */
13323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#undef TD
13423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#undef TF
13523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#undef TI
13623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#undef TN
13723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#undef TP
13823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#undef TS
13923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#undef TM
14023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#undef NF
14123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#undef MA
14223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
14323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)/*
14423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * `ioctlent.h' may be generated from `ioctlent.raw' by the auxiliary
14523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * program `ioctlsort', such that the list is sorted by the `code' field.
14623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * This has the side-effect of resolving the _IO.. macros into
14723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * plain integers, eliminating the need to include here everything
14823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) * in "/usr/include".
14923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles) */
15023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
15123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static const char *const errnoent0[] = {
15223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#include "errnoent.h"
15323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)};
15423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static const char *const signalent0[] = {
15583750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch#include "signalent.h"
15623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)};
15723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static const struct ioctlent ioctlent0[] = {
15823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#include "ioctlent.h"
15923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)};
1607757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochenum { nsyscalls0 = ARRAY_SIZE(sysent0) };
16123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)enum { nerrnos0 = ARRAY_SIZE(errnoent0) };
16223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)enum { nsignals0 = ARRAY_SIZE(signalent0) };
16323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)enum { nioctlents0 = ARRAY_SIZE(ioctlent0) };
16423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)int qual_flags0[MAX_QUALS];
16523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
166591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#if SUPPORTED_PERSONALITIES >= 2
16723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static const char *const errnoent1[] = {
1680019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch# include "errnoent1.h"
169e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch};
170e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochstatic const char *const signalent1[] = {
17123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# include "signalent1.h"
172e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch};
173e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochstatic const struct ioctlent ioctlent1[] = {
17423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# include "ioctlent1.h"
17523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)};
17623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)enum { nsyscalls1 = ARRAY_SIZE(sysent1) };
177591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochenum { nerrnos1 = ARRAY_SIZE(errnoent1) };
17823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)enum { nsignals1 = ARRAY_SIZE(signalent1) };
17923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)enum { nioctlents1 = ARRAY_SIZE(ioctlent1) };
18023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)int qual_flags1[MAX_QUALS];
18123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
18223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
18323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#if SUPPORTED_PERSONALITIES >= 3
18423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static const char *const errnoent2[] = {
18523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# include "errnoent2.h"
18623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)};
18723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static const char *const signalent2[] = {
18823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# include "signalent2.h"
18923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)};
19023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static const struct ioctlent ioctlent2[] = {
19123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# include "ioctlent2.h"
19223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)};
19323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)enum { nsyscalls2 = ARRAY_SIZE(sysent2) };
19423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)enum { nerrnos2 = ARRAY_SIZE(errnoent2) };
19523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)enum { nsignals2 = ARRAY_SIZE(signalent2) };
19623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)enum { nioctlents2 = ARRAY_SIZE(ioctlent2) };
19723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)int qual_flags2[MAX_QUALS];
19823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
19923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
20023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)const struct sysent *sysent = sysent0;
20123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)const char *const *errnoent = errnoent0;
20223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)const char *const *signalent = signalent0;
20323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)const struct ioctlent *ioctlent = ioctlent0;
20423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)unsigned nsyscalls = nsyscalls0;
20523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)unsigned nerrnos = nerrnos0;
20623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)unsigned nsignals = nsignals0;
20723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)unsigned nioctlents = nioctlents0;
20823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)int *qual_flags = qual_flags0;
20923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
21023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#if SUPPORTED_PERSONALITIES > 1
21123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)int current_personality;
21223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
21323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
21423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	PERSONALITY0_WORDSIZE,
21523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	PERSONALITY1_WORDSIZE,
21623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# if SUPPORTED_PERSONALITIES > 2
21723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	PERSONALITY2_WORDSIZE,
21823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# endif
21923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)};
22023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
22123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)void
22223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)set_personality(int personality)
22323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles){
22423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	switch (personality) {
22523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	case 0:
22623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		errnoent = errnoent0;
22723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		nerrnos = nerrnos0;
22823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		sysent = sysent0;
22923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		nsyscalls = nsyscalls0;
23023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		ioctlent = ioctlent0;
23123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		nioctlents = nioctlents0;
23223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		signalent = signalent0;
23323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		nsignals = nsignals0;
23423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		qual_flags = qual_flags0;
23523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		break;
23623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
237591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	case 1:
23823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		errnoent = errnoent1;
23923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		nerrnos = nerrnos1;
240591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		sysent = sysent1;
24123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		nsyscalls = nsyscalls1;
24223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		ioctlent = ioctlent1;
24323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		nioctlents = nioctlents1;
24423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		signalent = signalent1;
245591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		nsignals = nsignals1;
24623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		qual_flags = qual_flags1;
24723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		break;
24823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
24923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# if SUPPORTED_PERSONALITIES >= 3
25023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	case 2:
25123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		errnoent = errnoent2;
25223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		nerrnos = nerrnos2;
25323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		sysent = sysent2;
25423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		nsyscalls = nsyscalls2;
25523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		ioctlent = ioctlent2;
25623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		nioctlents = nioctlents2;
25723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		signalent = signalent2;
25823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		nsignals = nsignals2;
25923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		qual_flags = qual_flags2;
26023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		break;
26123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# endif
26223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
26323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
26423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	current_personality = personality;
26523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)}
26623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
26723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static void
26823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)update_personality(struct tcb *tcp, int personality)
26923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles){
27023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (personality == current_personality)
27123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return;
27223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	set_personality(personality);
27323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
27423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (personality == tcp->currpers)
27523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return;
27623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	tcp->currpers = personality;
27723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
27823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# if defined(POWERPC64)
27923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (!qflag) {
28023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		static const char *const names[] = {"64 bit", "32 bit"};
28123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
28223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			tcp->pid, names[personality]);
28323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
28423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# elif defined(X86_64)
28523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (!qflag) {
28623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		static const char *const names[] = {"64 bit", "32 bit", "x32"};
28723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
28823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			tcp->pid, names[personality]);
28923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
29023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# elif defined(X32)
29123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (!qflag) {
29223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		static const char *const names[] = {"x32", "32 bit"};
29323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
29423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			tcp->pid, names[personality]);
295591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	}
29623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# elif defined(AARCH64)
29723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (!qflag) {
29823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		static const char *const names[] = {"32-bit ARM", "AArch64"};
29923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
30023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			tcp->pid, names[personality]);
30123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
30223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# elif defined(TILE)
30323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (!qflag) {
30423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		static const char *const names[] = {"64-bit", "32-bit"};
30523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		fprintf(stderr, "[ Process PID=%d runs in %s mode. ]\n",
30623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			tcp->pid, names[personality]);
30723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
30823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# endif
30923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)}
31023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
31123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
31223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
31323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
31423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static const struct qual_options {
31523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	int bitflag;
31623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	const char *option_name;
31723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	int (*qualify)(const char *, int, int);
31823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	const char *argument_name;
31923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)} qual_options[] = {
32023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_TRACE,	"trace",	qual_syscall,	"system call"	},
32123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_TRACE,	"t",		qual_syscall,	"system call"	},
32223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_ABBREV,	"abbrev",	qual_syscall,	"system call"	},
32323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_ABBREV,	"a",		qual_syscall,	"system call"	},
32423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_VERBOSE,	"verbose",	qual_syscall,	"system call"	},
32523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_VERBOSE,	"v",		qual_syscall,	"system call"	},
32623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_RAW,	"raw",		qual_syscall,	"system call"	},
32723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_RAW,	"x",		qual_syscall,	"system call"	},
32823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_SIGNAL,	"signal",	qual_signal,	"signal"	},
329591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	{ QUAL_SIGNAL,	"signals",	qual_signal,	"signal"	},
33023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_SIGNAL,	"s",		qual_signal,	"signal"	},
33123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_FAULT,	"fault",	qual_fault,	"fault"		},
33223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_FAULT,	"faults",	qual_fault,	"fault"		},
33323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_FAULT,	"m",		qual_fault,	"fault"		},
33423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_READ,	"read",		qual_desc,	"descriptor"	},
33523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_READ,	"reads",	qual_desc,	"descriptor"	},
33623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_READ,	"r",		qual_desc,	"descriptor"	},
33723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_WRITE,	"write",	qual_desc,	"descriptor"	},
33823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_WRITE,	"writes",	qual_desc,	"descriptor"	},
33923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ QUAL_WRITE,	"w",		qual_desc,	"descriptor"	},
34023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	{ 0,		NULL,		NULL,		NULL		},
341591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch};
34223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
34323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static void
34423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)qualify_one(int n, int bitflag, int not, int pers)
34523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles){
34623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (pers == 0 || pers < 0) {
34723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		if (not)
34823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			qual_flags0[n] &= ~bitflag;
34923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		else
35023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			qual_flags0[n] |= bitflag;
35123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
35223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
35323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#if SUPPORTED_PERSONALITIES >= 2
35423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (pers == 1 || pers < 0) {
35523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		if (not)
35623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			qual_flags1[n] &= ~bitflag;
35723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		else
35823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			qual_flags1[n] |= bitflag;
35923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
36023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
36123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
36223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#if SUPPORTED_PERSONALITIES >= 3
36323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (pers == 2 || pers < 0) {
36423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		if (not)
36523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			qual_flags2[n] &= ~bitflag;
36623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		else
36723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			qual_flags2[n] |= bitflag;
36823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
36923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
37023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)}
371e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
37223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static int
37323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)qual_syscall(const char *s, int bitflag, int not)
37423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles){
37523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	int i;
37623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	int rc = -1;
37723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
3787757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch	if (*s >= '0' && *s <= '9') {
3797757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch		int i = string_to_uint(s);
38023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		if (i < 0 || i >= MAX_QUALS)
38123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			return -1;
38223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		qualify_one(i, bitflag, not, -1);
38323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return 0;
38423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
38523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	for (i = 0; i < nsyscalls0; i++)
38623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		if (sysent0[i].sys_name &&
38723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		    strcmp(s, sysent0[i].sys_name) == 0) {
38823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			qualify_one(i, bitflag, not, 0);
38923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			rc = 0;
39023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		}
39123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
392e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#if SUPPORTED_PERSONALITIES >= 2
393e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch	for (i = 0; i < nsyscalls1; i++)
39423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		if (sysent1[i].sys_name &&
39523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		    strcmp(s, sysent1[i].sys_name) == 0) {
39623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			qualify_one(i, bitflag, not, 1);
39723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			rc = 0;
39823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		}
39923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
40023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
40123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#if SUPPORTED_PERSONALITIES >= 3
40223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	for (i = 0; i < nsyscalls2; i++)
4030019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch		if (sysent2[i].sys_name &&
4040019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch		    strcmp(s, sysent2[i].sys_name) == 0) {
40523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			qualify_one(i, bitflag, not, 2);
40623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			rc = 0;
40723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		}
40823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
40923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
41023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	return rc;
41123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)}
41223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
41323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static int
41423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)qual_signal(const char *s, int bitflag, int not)
41523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles){
41623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	int i;
41723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
41823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (*s >= '0' && *s <= '9') {
41923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		int signo = string_to_uint(s);
42023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		if (signo < 0 || signo >= MAX_QUALS)
42123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			return -1;
42223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		qualify_one(signo, bitflag, not, -1);
42323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return 0;
42423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
42523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (strncasecmp(s, "SIG", 3) == 0)
42623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		s += 3;
42723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	for (i = 0; i <= NSIG; i++) {
42823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		if (strcasecmp(s, signame(i) + 3) == 0) {
42923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			qualify_one(i, bitflag, not, -1);
43023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			return 0;
43123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		}
43223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
43323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	return -1;
43423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)}
43523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
43623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static int
43723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)qual_fault(const char *s, int bitflag, int not)
43823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles){
43923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	return -1;
44023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)}
44123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
44223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static int
44323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)qual_desc(const char *s, int bitflag, int not)
44423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles){
44523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (*s >= '0' && *s <= '9') {
44623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		int desc = string_to_uint(s);
44723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		if (desc < 0 || desc >= MAX_QUALS)
44823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			return -1;
44923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		qualify_one(desc, bitflag, not, -1);
45023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return 0;
45123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
45223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	return -1;
45323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)}
454591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
45523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static int
45623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)lookup_class(const char *s)
457591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
45823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (strcmp(s, "file") == 0)
45923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return TRACE_FILE;
46023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (strcmp(s, "ipc") == 0)
4617757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch		return TRACE_IPC;
462591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	if (strcmp(s, "network") == 0)
46323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return TRACE_NETWORK;
46423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (strcmp(s, "process") == 0)
46523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return TRACE_PROCESS;
46623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (strcmp(s, "signal") == 0)
46723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return TRACE_SIGNAL;
4687757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch	if (strcmp(s, "desc") == 0)
46923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return TRACE_DESC;
47023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (strcmp(s, "memory") == 0)
471e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch		return TRACE_MEMORY;
47223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	return -1;
47323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)}
47423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
47523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)void
47623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)qualify(const char *s)
47723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles){
47823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	const struct qual_options *opt;
47923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	int not;
48023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	char *copy;
48123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	const char *p;
48223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	int i, n;
48323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
48423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	opt = &qual_options[0];
48523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	for (i = 0; (p = qual_options[i].option_name); i++) {
48623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		n = strlen(p);
48723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		if (strncmp(s, p, n) == 0 && s[n] == '=') {
48823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			opt = &qual_options[i];
48923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			s += n + 1;
49023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			break;
49123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		}
49223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
49323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	not = 0;
49423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (*s == '!') {
49523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		not = 1;
49623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		s++;
49723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
49823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (strcmp(s, "none") == 0) {
49923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		not = 1 - not;
50023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		s = "all";
50123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
50223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (strcmp(s, "all") == 0) {
503591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		for (i = 0; i < MAX_QUALS; i++) {
50423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			qualify_one(i, opt->bitflag, not, -1);
50523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		}
50623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return;
50723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
50823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	for (i = 0; i < MAX_QUALS; i++) {
50923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		qualify_one(i, opt->bitflag, !not, -1);
51023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
51123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	copy = strdup(s);
51223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (!copy)
51323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		die_out_of_memory();
51423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
51523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
51623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			for (i = 0; i < nsyscalls0; i++)
51723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)				if (sysent0[i].sys_flags & n)
51823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)					qualify_one(i, opt->bitflag, not, 0);
51923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
52023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#if SUPPORTED_PERSONALITIES >= 2
52123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			for (i = 0; i < nsyscalls1; i++)
52223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)				if (sysent1[i].sys_flags & n)
52323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)					qualify_one(i, opt->bitflag, not, 1);
52423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
52523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
52623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#if SUPPORTED_PERSONALITIES >= 3
52723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			for (i = 0; i < nsyscalls2; i++)
52823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)				if (sysent2[i].sys_flags & n)
52923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)					qualify_one(i, opt->bitflag, not, 2);
53023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
53123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
53223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			continue;
53323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		}
53423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		if (opt->qualify(p, opt->bitflag, not)) {
53523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			error_msg_and_die("invalid %s '%s'",
53623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)				opt->argument_name, p);
53723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		}
53823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
539591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	free(copy);
540521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)	return;
54123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)}
54223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
543e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#ifdef SYS_socket_subcall
544e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochstatic void
54523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)decode_socket_subcall(struct tcb *tcp)
54623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles){
54723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	unsigned long addr;
54823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	unsigned int i, size;
54983750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch
55023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
55123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return;
55223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
55323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
55423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	addr = tcp->u_arg[1];
555521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)	tcp->u_nargs = sysent[tcp->scno].nargs;
55623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	size = current_wordsize;
55723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	for (i = 0; i < tcp->u_nargs; ++i) {
55823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		if (size == sizeof(int)) {
55923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			unsigned int arg;
56023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			if (umove(tcp, addr, &arg) < 0)
56123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)				arg = 0;
56223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			tcp->u_arg[i] = arg;
563521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)		}
56423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		else {
56523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			unsigned long arg;
56623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			if (umove(tcp, addr, &arg) < 0)
56723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)				arg = 0;
56823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			tcp->u_arg[i] = arg;
56923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		}
57023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		addr += size;
57123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
57223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)}
57323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
57423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
57523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#ifdef SYS_ipc_subcall
57623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)static void
57723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)decode_ipc_subcall(struct tcb *tcp)
57823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles){
57983750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch	unsigned int i;
58083750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch
58123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
58283750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch		return;
58383750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch
58423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
58523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	tcp->u_nargs = sysent[tcp->scno].nargs;
58623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	for (i = 0; i < tcp->u_nargs; i++)
58723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		tcp->u_arg[i] = tcp->u_arg[i + 1];
58823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)}
58923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#endif
59023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
59123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)int
59223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)printargs(struct tcb *tcp)
59323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles){
59423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (entering(tcp)) {
59523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		int i;
59623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
59723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		for (i = 0; i < tcp->u_nargs; i++)
59823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
59923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
600591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	return 0;
601591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
602591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
603591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochint
604591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochprintargs_lu(struct tcb *tcp)
605591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
606591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	if (entering(tcp)) {
607591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		int i;
608591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
609591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		for (i = 0; i < tcp->u_nargs; i++)
610591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
611591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	}
612591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	return 0;
613591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
614591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
61583750176c3ee2cea66c8a9751271026a5901be3aBen Murdochint
616591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochprintargs_ld(struct tcb *tcp)
617591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
618591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	if (entering(tcp)) {
619591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		int i;
620591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
621591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		for (i = 0; i < tcp->u_nargs; i++)
622591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
623591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	}
624591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	return 0;
625591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
626591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
627591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#if defined(SPARC) || defined(SPARC64) || defined(IA64) || defined(SH)
628591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochlong
629591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochgetrval2(struct tcb *tcp)
630591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
631591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	long val;
632591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
633591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch# if defined(SPARC) || defined(SPARC64)
634591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	val = regs.u_regs[U_REG_O1];
635591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch# elif defined(SH)
636591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
637591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		return -1;
638591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch# elif defined(IA64)
639591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	if (upeek(tcp, PT_R9, &val) < 0)
640591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		return -1;
641591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch# endif
6420019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch
643591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	return val;
644591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
645591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#endif
646591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
647591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochint
648591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochis_restart_error(struct tcb *tcp)
649591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
650591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	switch (tcp->u_error) {
651591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		case ERESTARTSYS:
652591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		case ERESTARTNOINTR:
653591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		case ERESTARTNOHAND:
654591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		case ERESTART_RESTARTBLOCK:
655591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			return 1;
656591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		default:
657591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			break;
658591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	}
659591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	return 0;
660591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
661591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
662591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#if defined(I386)
663591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstruct pt_regs i386_regs;
664591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(X86_64) || defined(X32)
665591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch/*
666591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * On 32 bits, pt_regs and user_regs_struct are the same,
667591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * but on 64 bits, user_regs_struct has six more fields:
668591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * fs_base, gs_base, ds, es, fs, gs.
669591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * PTRACE_GETREGS fills them too, so struct pt_regs would overflow.
670591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch */
671591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic struct user_regs_struct x86_64_regs;
672591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(IA64)
673591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochlong r8, r10; /* TODO: make static? */
674591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochlong ia32 = 0; /* not static */
675591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(POWERPC)
676591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic long ppc_result;
677591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(M68K)
678591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic long d0;
679591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(BFIN)
680591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic long r0;
681591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(ARM)
682591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstruct pt_regs regs; /* not static */
683591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(AARCH64)
684591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic struct user_pt_regs aarch64_regs;
685591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic struct arm_pt_regs regs;
686591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic struct iovec aarch64_io = {
687591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	.iov_base = &aarch64_regs
688591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch};
689591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(ALPHA)
690591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic long r0;
691591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic long a3;
692591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(AVR32)
693591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic struct pt_regs regs;
694591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(SPARC) || defined(SPARC64)
695591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstruct pt_regs regs; /* not static */
696591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(LINUX_MIPSN32)
697591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic long long a3;
698591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic long long r2;
699591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(MIPS)
700591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic long a3;
701591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic long r2;
702591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(S390) || defined(S390X)
703e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochstatic long gpr2;
704e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochstatic long pc;
705591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic long syscall_mode;
706591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(HPPA)
707591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic long r28;
708591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(SH)
70983750176c3ee2cea66c8a9751271026a5901be3aBen Murdochstatic long r0;
710591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(SH64)
711591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic long r9;
712591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(CRISV10) || defined(CRISV32)
713591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic long r10;
714591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(TILE)
715591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstruct pt_regs tile_regs;
716591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(MICROBLAZE)
717591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic long r3;
718591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#endif
719591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
720591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid
721591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochprintcall(struct tcb *tcp)
722591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
723591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
724591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			   sizeof(long) == 8 ? "[????????????????] " : \
725591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			   NULL /* crash */)
726591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	if (get_regs_error) {
727591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		PRINTBADPC;
728591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		return;
729591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	}
730591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#if defined(I386)
731591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	tprintf("[%08lx] ", i386_regs.eip);
732591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(S390) || defined(S390X)
733591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	long psw;
734591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	if (upeek(tcp, PT_PSWADDR, &psw) < 0) {
735591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		PRINTBADPC;
736591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		return;
737591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	}
738591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch# ifdef S390
73983750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch	tprintf("[%08lx] ", psw);
74083750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch# elif S390X
741591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	tprintf("[%016lx] ", psw);
74283750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch# endif
74383750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch#elif defined(X86_64) || defined(X32)
744591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	tprintf("[%016lx] ", (unsigned long) x86_64_regs.rip);
745591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(IA64)
746591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	long ip;
747591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
748591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	if (upeek(tcp, PT_B0, &ip) < 0) {
749591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		PRINTBADPC;
750591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		return;
751591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	}
752591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	tprintf("[%08lx] ", ip);
753591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(POWERPC)
754591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	long pc;
755591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
756591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	if (upeek(tcp, sizeof(unsigned long)*PT_NIP, &pc) < 0) {
757591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		PRINTBADPC;
758591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		return;
759591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	}
760591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch# ifdef POWERPC64
76123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	tprintf("[%016lx] ", pc);
76223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# else
76323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	tprintf("[%08lx] ", pc);
76423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# endif
76523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#elif defined(M68K)
76623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	long pc;
76723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
76823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (upeek(tcp, 4*PT_PC, &pc) < 0) {
76923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		tprints("[????????] ");
77023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return;
771521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)	}
77223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	tprintf("[%08lx] ", pc);
77323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#elif defined(ALPHA)
77423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	long pc;
77583750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch
77623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (upeek(tcp, REG_PC, &pc) < 0) {
77723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		tprints("[????????????????] ");
77823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return;
77923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
78023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	tprintf("[%08lx] ", pc);
78123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#elif defined(SPARC)
782591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	tprintf("[%08lx] ", regs.pc);
78323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#elif defined(SPARC64)
78423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	tprintf("[%08lx] ", regs.tpc);
78523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#elif defined(HPPA)
78623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	long pc;
78723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
78823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (upeek(tcp, PT_IAOQ0, &pc) < 0) {
78923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		tprints("[????????] ");
790521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)		return;
79123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
79223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	tprintf("[%08lx] ", pc);
79323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#elif defined(MIPS)
79423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	long pc;
79523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
79623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (upeek(tcp, REG_EPC, &pc) < 0) {
79723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		tprints("[????????] ");
79823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return;
79923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
80023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	tprintf("[%08lx] ", pc);
80123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#elif defined(SH)
8020019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch	long pc;
80323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
80423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (upeek(tcp, 4*REG_PC, &pc) < 0) {
80523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		tprints("[????????] ");
80623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return;
80723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
80823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	tprintf("[%08lx] ", pc);
809591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(SH64)
81023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	long pc;
81123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
81223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (upeek(tcp, REG_PC, &pc) < 0) {
81323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		tprints("[????????????????] ");
81423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return;
81523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
81623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	tprintf("[%08lx] ", pc);
81723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#elif defined(ARM)
81823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	tprintf("[%08lx] ", regs.ARM_pc);
81923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)/*#elif defined(AARCH64) ??? */
82023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#elif defined(AVR32)
821591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	tprintf("[%08lx] ", regs.pc);
822591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(BFIN)
823591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	long pc;
824591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
82523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (upeek(tcp, PT_PC, &pc) < 0) {
82623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		PRINTBADPC;
827591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		return;
82823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
82923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	tprintf("[%08lx] ", pc);
83023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#elif defined(CRISV10)
83123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	long pc;
83223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
83323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (upeek(tcp, 4*PT_IRP, &pc) < 0) {
83423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		PRINTBADPC;
83523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return;
83623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	}
83723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	tprintf("[%08lx] ", pc);
83823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)#elif defined(CRISV32)
83923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	long pc;
84023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)
84123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (upeek(tcp, 4*PT_ERP, &pc) < 0) {
842591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		PRINTBADPC;
843591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		return;
844591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	}
845591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	tprintf("[%08lx] ", pc);
846591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#elif defined(TILE)
847591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch# ifdef _LP64
848591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	tprintf("[%016lx] ", (unsigned long) tile_regs.pc);
849591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch# else
850591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	tprintf("[%08lx] ", (unsigned long) tile_regs.pc);
851591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch# endif
852591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#endif /* architecture */
853591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
854591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
855591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#ifndef get_regs
856591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochlong get_regs_error;
857591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid get_regs(pid_t pid)
858591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
85923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# if defined(AVR32)
86083750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch	get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
86123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# elif defined(I386)
86223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &i386_regs);
86323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# elif defined(X86_64) || defined(X32)
86423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &x86_64_regs);
86523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)# elif defined(AARCH64)
86623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	/*aarch64_io.iov_base = &aarch64_regs; - already is */
86723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	aarch64_io.iov_len = sizeof(aarch64_regs);
86823042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	get_regs_error = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void *)&aarch64_io);
86923042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	if (get_regs_error)
87023042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		return;
87123042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)	switch (aarch64_io.iov_len) {
87223042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		case sizeof(regs):
87323042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			/* We are in 32-bit mode */
87423042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			memcpy(&regs, &aarch64_regs, sizeof(regs));
87523042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			break;
87623042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)		case sizeof(aarch64_regs):
87723042b77ca894a768b5747ff08f587ed8222772aTorne (Richard Coles)			/* We are in 64-bit mode */
878			/* Data is already in aarch64_regs */
879			break;
880		default:
881			get_regs_error = -1;
882			break;
883	}
884# elif defined(ARM)
885	get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (void *)&regs);
886# elif defined(SPARC) || defined(SPARC64)
887	get_regs_error = ptrace(PTRACE_GETREGS, pid, (char *)&regs, 0);
888# elif defined(TILE)
889	get_regs_error = ptrace(PTRACE_GETREGS, pid, NULL, (long) &tile_regs);
890# endif
891}
892#endif
893
894/* Returns:
895 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
896 * 1: ok, continue in trace_syscall_entering().
897 * other: error, trace_syscall_entering() should print error indicator
898 *    ("????" etc) and bail out.
899 */
900static int
901get_scno(struct tcb *tcp)
902{
903	long scno = 0;
904
905#if defined(S390) || defined(S390X)
906	if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
907		return -1;
908
909	if (syscall_mode != -ENOSYS) {
910		/*
911		 * Since kernel version 2.5.44 the scno gets passed in gpr2.
912		 */
913		scno = syscall_mode;
914	} else {
915		/*
916		 * Old style of "passing" the scno via the SVC instruction.
917		 */
918		long opcode, offset_reg, tmp;
919		void *svc_addr;
920		static const int gpr_offset[16] = {
921				PT_GPR0,  PT_GPR1,  PT_ORIGGPR2, PT_GPR3,
922				PT_GPR4,  PT_GPR5,  PT_GPR6,     PT_GPR7,
923				PT_GPR8,  PT_GPR9,  PT_GPR10,    PT_GPR11,
924				PT_GPR12, PT_GPR13, PT_GPR14,    PT_GPR15
925		};
926
927		if (upeek(tcp, PT_PSWADDR, &pc) < 0)
928			return -1;
929		errno = 0;
930		opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
931		if (errno) {
932			perror_msg("%s", "peektext(pc-oneword)");
933			return -1;
934		}
935
936		/*
937		 *  We have to check if the SVC got executed directly or via an
938		 *  EXECUTE instruction. In case of EXECUTE it is necessary to do
939		 *  instruction decoding to derive the system call number.
940		 *  Unfortunately the opcode sizes of EXECUTE and SVC are differently,
941		 *  so that this doesn't work if a SVC opcode is part of an EXECUTE
942		 *  opcode. Since there is no way to find out the opcode size this
943		 *  is the best we can do...
944		 */
945		if ((opcode & 0xff00) == 0x0a00) {
946			/* SVC opcode */
947			scno = opcode & 0xff;
948		}
949		else {
950			/* SVC got executed by EXECUTE instruction */
951
952			/*
953			 *  Do instruction decoding of EXECUTE. If you really want to
954			 *  understand this, read the Principles of Operations.
955			 */
956			svc_addr = (void *) (opcode & 0xfff);
957
958			tmp = 0;
959			offset_reg = (opcode & 0x000f0000) >> 16;
960			if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
961				return -1;
962			svc_addr += tmp;
963
964			tmp = 0;
965			offset_reg = (opcode & 0x0000f000) >> 12;
966			if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
967				return -1;
968			svc_addr += tmp;
969
970			scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
971			if (errno)
972				return -1;
973# if defined(S390X)
974			scno >>= 48;
975# else
976			scno >>= 16;
977# endif
978			tmp = 0;
979			offset_reg = (opcode & 0x00f00000) >> 20;
980			if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
981				return -1;
982
983			scno = (scno | tmp) & 0xff;
984		}
985	}
986#elif defined(POWERPC)
987	if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
988		return -1;
989# ifdef POWERPC64
990	/* TODO: speed up strace by not doing this at every syscall.
991	 * We only need to do it after execve.
992	 */
993	int currpers;
994	long val;
995
996	/* Check for 64/32 bit mode. */
997	if (upeek(tcp, sizeof(unsigned long)*PT_MSR, &val) < 0)
998		return -1;
999	/* SF is bit 0 of MSR */
1000	if (val < 0)
1001		currpers = 0;
1002	else
1003		currpers = 1;
1004	update_personality(tcp, currpers);
1005# endif
1006#elif defined(AVR32)
1007	scno = regs.r8;
1008#elif defined(BFIN)
1009	if (upeek(tcp, PT_ORIG_P0, &scno))
1010		return -1;
1011#elif defined(I386)
1012	scno = i386_regs.orig_eax;
1013#elif defined(X86_64) || defined(X32)
1014# ifndef __X32_SYSCALL_BIT
1015#  define __X32_SYSCALL_BIT	0x40000000
1016# endif
1017# ifndef __X32_SYSCALL_MASK
1018#  define __X32_SYSCALL_MASK	__X32_SYSCALL_BIT
1019# endif
1020
1021	int currpers;
1022	scno = x86_64_regs.orig_rax;
1023
1024	/* Check CS register value. On x86-64 linux it is:
1025	 *	0x33	for long mode (64 bit)
1026	 *	0x23	for compatibility mode (32 bit)
1027	 * Check DS register value. On x86-64 linux it is:
1028	 *	0x2b	for x32 mode (x86-64 in 32 bit)
1029	 */
1030	switch (x86_64_regs.cs) {
1031		case 0x23: currpers = 1; break;
1032		case 0x33:
1033			if (x86_64_regs.ds == 0x2b) {
1034				currpers = 2;
1035				scno &= ~__X32_SYSCALL_MASK;
1036			} else
1037				currpers = 0;
1038			break;
1039		default:
1040			fprintf(stderr, "Unknown value CS=0x%08X while "
1041				 "detecting personality of process "
1042				 "PID=%d\n", (int)x86_64_regs.cs, tcp->pid);
1043			currpers = current_personality;
1044			break;
1045	}
1046# if 0
1047	/* This version analyzes the opcode of a syscall instruction.
1048	 * (int 0x80 on i386 vs. syscall on x86-64)
1049	 * It works, but is too complicated.
1050	 */
1051	unsigned long val, rip, i;
1052
1053	rip = x86_64_regs.rip;
1054
1055	/* sizeof(syscall) == sizeof(int 0x80) == 2 */
1056	rip -= 2;
1057	errno = 0;
1058
1059	call = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)rip, (char *)0);
1060	if (errno)
1061		fprintf(stderr, "ptrace_peektext failed: %s\n",
1062				strerror(errno));
1063	switch (call & 0xffff) {
1064		/* x86-64: syscall = 0x0f 0x05 */
1065		case 0x050f: currpers = 0; break;
1066		/* i386: int 0x80 = 0xcd 0x80 */
1067		case 0x80cd: currpers = 1; break;
1068		default:
1069			currpers = current_personality;
1070			fprintf(stderr,
1071				"Unknown syscall opcode (0x%04X) while "
1072				"detecting personality of process "
1073				"PID=%d\n", (int)call, tcp->pid);
1074			break;
1075	}
1076# endif
1077# ifdef X32
1078	/* Value of currpers:
1079	 *   0: 64 bit
1080	 *   1: 32 bit
1081	 *   2: X32
1082	 * Value of current_personality:
1083	 *   0: X32
1084	 *   1: 32 bit
1085	 */
1086	switch (currpers) {
1087		case 0:
1088			fprintf(stderr, "syscall_%lu (...) in unsupported "
1089					"64-bit mode of process PID=%d\n",
1090				scno, tcp->pid);
1091			return 0;
1092		case 2:
1093			currpers = 0;
1094	}
1095# endif
1096	update_personality(tcp, currpers);
1097#elif defined(IA64)
1098#	define IA64_PSR_IS	((long)1 << 34)
1099	long psr;
1100	if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1101		ia32 = (psr & IA64_PSR_IS) != 0;
1102	if (ia32) {
1103		if (upeek(tcp, PT_R1, &scno) < 0)
1104			return -1;
1105	} else {
1106		if (upeek(tcp, PT_R15, &scno) < 0)
1107			return -1;
1108	}
1109#elif defined(AARCH64)
1110	switch (aarch64_io.iov_len) {
1111		case sizeof(aarch64_regs):
1112			/* We are in 64-bit mode */
1113			scno = aarch64_regs.regs[8];
1114			update_personality(tcp, 1);
1115			break;
1116		case sizeof(regs):
1117			/* We are in 32-bit mode */
1118			scno = regs.uregs[7];
1119			update_personality(tcp, 0);
1120			break;
1121	}
1122#elif defined(ARM)
1123	/*
1124	 * We only need to grab the syscall number on syscall entry.
1125	 */
1126	if (regs.ARM_ip == 0) {
1127		/*
1128		 * Note: we only deal with only 32-bit CPUs here.
1129		 */
1130		if (regs.ARM_cpsr & 0x20) {
1131			/*
1132			 * Get the Thumb-mode system call number
1133			 */
1134			scno = regs.ARM_r7;
1135		} else {
1136			/*
1137			 * Get the ARM-mode system call number
1138			 */
1139			errno = 0;
1140			scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
1141			if (errno)
1142				return -1;
1143
1144			/* Handle the EABI syscall convention.  We do not
1145			   bother converting structures between the two
1146			   ABIs, but basic functionality should work even
1147			   if strace and the traced program have different
1148			   ABIs.  */
1149			if (scno == 0xef000000) {
1150				scno = regs.ARM_r7;
1151			} else {
1152				if ((scno & 0x0ff00000) != 0x0f900000) {
1153					fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1154						scno);
1155					return -1;
1156				}
1157
1158				/*
1159				 * Fixup the syscall number
1160				 */
1161				scno &= 0x000fffff;
1162			}
1163		}
1164		if (scno & 0x0f0000) {
1165			/*
1166			 * Handle ARM specific syscall
1167			 */
1168			update_personality(tcp, 1);
1169			scno &= 0x0000ffff;
1170		} else
1171			update_personality(tcp, 0);
1172
1173	} else {
1174		fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1175		tcp->flags |= TCB_INSYSCALL;
1176	}
1177#elif defined(M68K)
1178	if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
1179		return -1;
1180#elif defined(LINUX_MIPSN32)
1181	unsigned long long regs[38];
1182
1183	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1184		return -1;
1185	a3 = regs[REG_A3];
1186	r2 = regs[REG_V0];
1187
1188	scno = r2;
1189	if (!SCNO_IN_RANGE(scno)) {
1190		if (a3 == 0 || a3 == -1) {
1191			if (debug_flag)
1192				fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
1193			return 0;
1194		}
1195	}
1196#elif defined(MIPS)
1197	if (upeek(tcp, REG_A3, &a3) < 0)
1198		return -1;
1199	if (upeek(tcp, REG_V0, &scno) < 0)
1200		return -1;
1201
1202	if (!SCNO_IN_RANGE(scno)) {
1203		if (a3 == 0 || a3 == -1) {
1204			if (debug_flag)
1205				fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
1206			return 0;
1207		}
1208	}
1209#elif defined(ALPHA)
1210	if (upeek(tcp, REG_A3, &a3) < 0)
1211		return -1;
1212	if (upeek(tcp, REG_R0, &scno) < 0)
1213		return -1;
1214
1215	/*
1216	 * Do some sanity checks to figure out if it's
1217	 * really a syscall entry
1218	 */
1219	if (!SCNO_IN_RANGE(scno)) {
1220		if (a3 == 0 || a3 == -1) {
1221			if (debug_flag)
1222				fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
1223			return 0;
1224		}
1225	}
1226#elif defined(SPARC) || defined(SPARC64)
1227	/* Disassemble the syscall trap. */
1228	/* Retrieve the syscall trap instruction. */
1229	unsigned long trap;
1230	errno = 0;
1231# if defined(SPARC64)
1232	trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1233	trap >>= 32;
1234# else
1235	trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
1236# endif
1237	if (errno)
1238		return -1;
1239
1240	/* Disassemble the trap to see what personality to use. */
1241	switch (trap) {
1242	case 0x91d02010:
1243		/* Linux/SPARC syscall trap. */
1244		update_personality(tcp, 0);
1245		break;
1246	case 0x91d0206d:
1247		/* Linux/SPARC64 syscall trap. */
1248		update_personality(tcp, 2);
1249		break;
1250	case 0x91d02000:
1251		/* SunOS syscall trap. (pers 1) */
1252		fprintf(stderr, "syscall: SunOS no support\n");
1253		return -1;
1254	case 0x91d02008:
1255		/* Solaris 2.x syscall trap. (per 2) */
1256		update_personality(tcp, 1);
1257		break;
1258	case 0x91d02009:
1259		/* NetBSD/FreeBSD syscall trap. */
1260		fprintf(stderr, "syscall: NetBSD/FreeBSD not supported\n");
1261		return -1;
1262	case 0x91d02027:
1263		/* Solaris 2.x gettimeofday */
1264		update_personality(tcp, 1);
1265		break;
1266	default:
1267# if defined(SPARC64)
1268		fprintf(stderr, "syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
1269# else
1270		fprintf(stderr, "syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
1271# endif
1272		return -1;
1273	}
1274
1275	/* Extract the system call number from the registers. */
1276	if (trap == 0x91d02027)
1277		scno = 156;
1278	else
1279		scno = regs.u_regs[U_REG_G1];
1280	if (scno == 0) {
1281		scno = regs.u_regs[U_REG_O0];
1282		memmove(&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1283	}
1284#elif defined(HPPA)
1285	if (upeek(tcp, PT_GR20, &scno) < 0)
1286		return -1;
1287#elif defined(SH)
1288	/*
1289	 * In the new syscall ABI, the system call number is in R3.
1290	 */
1291	if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1292		return -1;
1293
1294	if (scno < 0) {
1295		/* Odd as it may seem, a glibc bug has been known to cause
1296		   glibc to issue bogus negative syscall numbers.  So for
1297		   our purposes, make strace print what it *should* have been */
1298		long correct_scno = (scno & 0xff);
1299		if (debug_flag)
1300			fprintf(stderr,
1301				"Detected glibc bug: bogus system call"
1302				" number = %ld, correcting to %ld\n",
1303				scno,
1304				correct_scno);
1305		scno = correct_scno;
1306	}
1307#elif defined(SH64)
1308	if (upeek(tcp, REG_SYSCALL, &scno) < 0)
1309		return -1;
1310	scno &= 0xFFFF;
1311#elif defined(CRISV10) || defined(CRISV32)
1312	if (upeek(tcp, 4*PT_R9, &scno) < 0)
1313		return -1;
1314#elif defined(TILE)
1315	int currpers;
1316	scno = tile_regs.regs[10];
1317# ifdef __tilepro__
1318	currpers = 1;
1319# else
1320	if (tile_regs.flags & PT_FLAGS_COMPAT)
1321		currpers = 1;
1322	else
1323		currpers = 0;
1324# endif
1325	update_personality(tcp, currpers);
1326
1327	if (!(tcp->flags & TCB_INSYSCALL)) {
1328		/* Check if we return from execve. */
1329		if (tcp->flags & TCB_WAITEXECVE) {
1330			tcp->flags &= ~TCB_WAITEXECVE;
1331			return 0;
1332		}
1333	}
1334#elif defined(MICROBLAZE)
1335	if (upeek(tcp, 0, &scno) < 0)
1336		return -1;
1337#endif
1338
1339#if defined(SH)
1340	/* new syscall ABI returns result in R0 */
1341	if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1342		return -1;
1343#elif defined(SH64)
1344	/* ABI defines result returned in r9 */
1345	if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1346		return -1;
1347#endif
1348
1349	tcp->scno = scno;
1350	return 1;
1351}
1352
1353/* Called at each syscall entry.
1354 * Returns:
1355 * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently.
1356 * 1: ok, continue in trace_syscall_entering().
1357 * other: error, trace_syscall_entering() should print error indicator
1358 *    ("????" etc) and bail out.
1359 */
1360static int
1361syscall_fixup_on_sysenter(struct tcb *tcp)
1362{
1363	/* A common case of "not a syscall entry" is post-execve SIGTRAP */
1364#if defined(I386)
1365	if (i386_regs.eax != -ENOSYS) {
1366		if (debug_flag)
1367			fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax);
1368		return 0;
1369	}
1370#elif defined(X86_64) || defined(X32)
1371	{
1372		long rax = x86_64_regs.rax;
1373		if (current_personality == 1)
1374			rax = (int)rax; /* sign extend from 32 bits */
1375		if (rax != -ENOSYS) {
1376			if (debug_flag)
1377				fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax);
1378			return 0;
1379		}
1380	}
1381#elif defined(S390) || defined(S390X)
1382	/* TODO: we already fetched PT_GPR2 in get_scno
1383	 * and stored it in syscall_mode, reuse it here
1384	 * instead of re-fetching?
1385	 */
1386	if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1387		return -1;
1388	if (syscall_mode != -ENOSYS)
1389		syscall_mode = tcp->scno;
1390	if (gpr2 != syscall_mode) {
1391		if (debug_flag)
1392			fprintf(stderr, "not a syscall entry (gpr2 = %ld)\n", gpr2);
1393		return 0;
1394	}
1395#elif defined(M68K)
1396	/* TODO? Eliminate upeek's in arches below like we did in x86 */
1397	if (upeek(tcp, 4*PT_D0, &d0) < 0)
1398		return -1;
1399	if (d0 != -ENOSYS) {
1400		if (debug_flag)
1401			fprintf(stderr, "not a syscall entry (d0 = %ld)\n", d0);
1402		return 0;
1403	}
1404#elif defined(IA64)
1405	if (upeek(tcp, PT_R10, &r10) < 0)
1406		return -1;
1407	if (upeek(tcp, PT_R8, &r8) < 0)
1408		return -1;
1409	if (ia32 && r8 != -ENOSYS) {
1410		if (debug_flag)
1411			fprintf(stderr, "not a syscall entry (r8 = %ld)\n", r8);
1412		return 0;
1413	}
1414#elif defined(CRISV10) || defined(CRISV32)
1415	if (upeek(tcp, 4*PT_R10, &r10) < 0)
1416		return -1;
1417	if (r10 != -ENOSYS) {
1418		if (debug_flag)
1419			fprintf(stderr, "not a syscall entry (r10 = %ld)\n", r10);
1420		return 0;
1421	}
1422#elif defined(MICROBLAZE)
1423	if (upeek(tcp, 3 * 4, &r3) < 0)
1424		return -1;
1425	if (r3 != -ENOSYS) {
1426		if (debug_flag)
1427			fprintf(stderr, "not a syscall entry (r3 = %ld)\n", r3);
1428		return 0;
1429	}
1430#endif
1431	return 1;
1432}
1433
1434static void
1435internal_fork(struct tcb *tcp)
1436{
1437#if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
1438# define ARG_FLAGS	1
1439#else
1440# define ARG_FLAGS	0
1441#endif
1442#ifndef CLONE_UNTRACED
1443# define CLONE_UNTRACED	0x00800000
1444#endif
1445	if ((ptrace_setoptions
1446	    & (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1447	   == (PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK))
1448		return;
1449
1450	if (!followfork)
1451		return;
1452
1453	if (entering(tcp)) {
1454		/*
1455		 * We won't see the new child if clone is called with
1456		 * CLONE_UNTRACED, so we keep the same logic with that option
1457		 * and don't trace it.
1458		 */
1459		if ((sysent[tcp->scno].sys_func == sys_clone) &&
1460		    (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
1461			return;
1462		setbpt(tcp);
1463	} else {
1464		if (tcp->flags & TCB_BPTSET)
1465			clearbpt(tcp);
1466	}
1467}
1468
1469#if defined(TCB_WAITEXECVE)
1470static void
1471internal_exec(struct tcb *tcp)
1472{
1473	/* Maybe we have post-execve SIGTRAP suppressed? */
1474	if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
1475		return; /* yes, no need to do anything */
1476
1477	if (exiting(tcp) && syserror(tcp))
1478		/* Error in execve, no post-execve SIGTRAP expected */
1479		tcp->flags &= ~TCB_WAITEXECVE;
1480	else
1481		tcp->flags |= TCB_WAITEXECVE;
1482}
1483#endif
1484
1485static void
1486syscall_fixup_for_fork_exec(struct tcb *tcp)
1487{
1488	/*
1489	 * We must always trace a few critical system calls in order to
1490	 * correctly support following forks in the presence of tracing
1491	 * qualifiers.
1492	 */
1493	int (*func)();
1494
1495	if (!SCNO_IN_RANGE(tcp->scno))
1496		return;
1497
1498	func = sysent[tcp->scno].sys_func;
1499
1500	if (   sys_fork == func
1501	    || sys_vfork == func
1502	    || sys_clone == func
1503	   ) {
1504		internal_fork(tcp);
1505		return;
1506	}
1507
1508#if defined(TCB_WAITEXECVE)
1509	if (   sys_execve == func
1510# if defined(SPARC) || defined(SPARC64)
1511	    || sys_execv == func
1512# endif
1513	   ) {
1514		internal_exec(tcp);
1515		return;
1516	}
1517#endif
1518}
1519
1520/* Return -1 on error or 1 on success (never 0!) */
1521static int
1522get_syscall_args(struct tcb *tcp)
1523{
1524	int i, nargs;
1525
1526	if (SCNO_IN_RANGE(tcp->scno))
1527		nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
1528	else
1529		nargs = tcp->u_nargs = MAX_ARGS;
1530
1531#if defined(S390) || defined(S390X)
1532	for (i = 0; i < nargs; ++i)
1533		if (upeek(tcp, i==0 ? PT_ORIGGPR2 : PT_GPR2 + i*sizeof(long), &tcp->u_arg[i]) < 0)
1534			return -1;
1535#elif defined(ALPHA)
1536	for (i = 0; i < nargs; ++i)
1537		if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
1538			return -1;
1539#elif defined(IA64)
1540	if (!ia32) {
1541		unsigned long *out0, cfm, sof, sol;
1542		long rbs_end;
1543		/* be backwards compatible with kernel < 2.4.4... */
1544#		ifndef PT_RBS_END
1545#		  define PT_RBS_END	PT_AR_BSP
1546#		endif
1547
1548		if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
1549			return -1;
1550		if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
1551			return -1;
1552
1553		sof = (cfm >> 0) & 0x7f;
1554		sol = (cfm >> 7) & 0x7f;
1555		out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
1556
1557		for (i = 0; i < nargs; ++i) {
1558			if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1559				   sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1560				return -1;
1561		}
1562	} else {
1563		static const int argreg[MAX_ARGS] = { PT_R11 /* EBX = out0 */,
1564						      PT_R9  /* ECX = out1 */,
1565						      PT_R10 /* EDX = out2 */,
1566						      PT_R14 /* ESI = out3 */,
1567						      PT_R15 /* EDI = out4 */,
1568						      PT_R13 /* EBP = out5 */};
1569
1570		for (i = 0; i < nargs; ++i) {
1571			if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1572				return -1;
1573			/* truncate away IVE sign-extension */
1574			tcp->u_arg[i] &= 0xffffffff;
1575		}
1576	}
1577#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
1578	/* N32 and N64 both use up to six registers.  */
1579	unsigned long long regs[38];
1580
1581	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1582		return -1;
1583
1584	for (i = 0; i < nargs; ++i) {
1585		tcp->u_arg[i] = regs[REG_A0 + i];
1586# if defined(LINUX_MIPSN32)
1587		tcp->ext_arg[i] = regs[REG_A0 + i];
1588# endif
1589	}
1590#elif defined(MIPS)
1591	if (nargs > 4) {
1592		long sp;
1593
1594		if (upeek(tcp, REG_SP, &sp) < 0)
1595			return -1;
1596		for (i = 0; i < 4; ++i)
1597			if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1598				return -1;
1599		umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
1600		       (char *)(tcp->u_arg + 4));
1601	} else {
1602		for (i = 0; i < nargs; ++i)
1603			if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
1604				return -1;
1605	}
1606#elif defined(POWERPC)
1607# ifndef PT_ORIG_R3
1608#  define PT_ORIG_R3 34
1609# endif
1610	for (i = 0; i < nargs; ++i) {
1611		if (upeek(tcp, (i==0) ?
1612			(sizeof(unsigned long) * PT_ORIG_R3) :
1613			((i+PT_R3) * sizeof(unsigned long)),
1614				&tcp->u_arg[i]) < 0)
1615			return -1;
1616	}
1617#elif defined(SPARC) || defined(SPARC64)
1618	for (i = 0; i < nargs; ++i)
1619		tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
1620#elif defined(HPPA)
1621	for (i = 0; i < nargs; ++i)
1622		if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1623			return -1;
1624#elif defined(ARM) || defined(AARCH64)
1625# if defined(AARCH64)
1626	if (tcp->currpers == 1)
1627		for (i = 0; i < nargs; ++i)
1628			tcp->u_arg[i] = aarch64_regs.regs[i];
1629	else
1630# endif /* AARCH64 */
1631	for (i = 0; i < nargs; ++i)
1632		tcp->u_arg[i] = regs.uregs[i];
1633#elif defined(AVR32)
1634	(void)i;
1635	(void)nargs;
1636	tcp->u_arg[0] = regs.r12;
1637	tcp->u_arg[1] = regs.r11;
1638	tcp->u_arg[2] = regs.r10;
1639	tcp->u_arg[3] = regs.r9;
1640	tcp->u_arg[4] = regs.r5;
1641	tcp->u_arg[5] = regs.r3;
1642#elif defined(BFIN)
1643	static const int argreg[MAX_ARGS] = { PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5 };
1644
1645	for (i = 0; i < nargs; ++i)
1646		if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
1647			return -1;
1648#elif defined(SH)
1649	static const int syscall_regs[MAX_ARGS] = {
1650		4 * (REG_REG0+4), 4 * (REG_REG0+5), 4 * (REG_REG0+6),
1651		4 * (REG_REG0+7), 4 * (REG_REG0  ), 4 * (REG_REG0+1)
1652	};
1653
1654	for (i = 0; i < nargs; ++i)
1655		if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
1656			return -1;
1657#elif defined(SH64)
1658	int i;
1659	/* Registers used by SH5 Linux system calls for parameters */
1660	static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
1661
1662	for (i = 0; i < nargs; ++i)
1663		if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
1664			return -1;
1665#elif defined(X86_64) || defined(X32)
1666	(void)i;
1667	(void)nargs;
1668	if (current_personality != 1) { /* x86-64 or x32 ABI */
1669		tcp->u_arg[0] = x86_64_regs.rdi;
1670		tcp->u_arg[1] = x86_64_regs.rsi;
1671		tcp->u_arg[2] = x86_64_regs.rdx;
1672		tcp->u_arg[3] = x86_64_regs.r10;
1673		tcp->u_arg[4] = x86_64_regs.r8;
1674		tcp->u_arg[5] = x86_64_regs.r9;
1675#  ifdef X32
1676		tcp->ext_arg[0] = x86_64_regs.rdi;
1677		tcp->ext_arg[1] = x86_64_regs.rsi;
1678		tcp->ext_arg[2] = x86_64_regs.rdx;
1679		tcp->ext_arg[3] = x86_64_regs.r10;
1680		tcp->ext_arg[4] = x86_64_regs.r8;
1681		tcp->ext_arg[5] = x86_64_regs.r9;
1682#  endif
1683	} else { /* i386 ABI */
1684		/* Sign-extend lower 32 bits */
1685		tcp->u_arg[0] = (long)(int)x86_64_regs.rbx;
1686		tcp->u_arg[1] = (long)(int)x86_64_regs.rcx;
1687		tcp->u_arg[2] = (long)(int)x86_64_regs.rdx;
1688		tcp->u_arg[3] = (long)(int)x86_64_regs.rsi;
1689		tcp->u_arg[4] = (long)(int)x86_64_regs.rdi;
1690		tcp->u_arg[5] = (long)(int)x86_64_regs.rbp;
1691	}
1692#elif defined(MICROBLAZE)
1693	for (i = 0; i < nargs; ++i)
1694		if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
1695			return -1;
1696#elif defined(CRISV10) || defined(CRISV32)
1697	static const int crisregs[MAX_ARGS] = {
1698		4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
1699		4*PT_R13     , 4*PT_MOF, 4*PT_SRP
1700	};
1701
1702	for (i = 0; i < nargs; ++i)
1703		if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
1704			return -1;
1705#elif defined(TILE)
1706	for (i = 0; i < nargs; ++i)
1707		tcp->u_arg[i] = tile_regs.regs[i];
1708#elif defined(M68K)
1709	for (i = 0; i < nargs; ++i)
1710		if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
1711			return -1;
1712#elif defined(I386)
1713	(void)i;
1714	(void)nargs;
1715	tcp->u_arg[0] = i386_regs.ebx;
1716	tcp->u_arg[1] = i386_regs.ecx;
1717	tcp->u_arg[2] = i386_regs.edx;
1718	tcp->u_arg[3] = i386_regs.esi;
1719	tcp->u_arg[4] = i386_regs.edi;
1720	tcp->u_arg[5] = i386_regs.ebp;
1721#else /* Other architecture (32bits specific) */
1722	for (i = 0; i < nargs; ++i)
1723		if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
1724			return -1;
1725#endif
1726	return 1;
1727}
1728
1729static int
1730trace_syscall_entering(struct tcb *tcp)
1731{
1732	int res, scno_good;
1733
1734#if defined TCB_WAITEXECVE
1735	if (tcp->flags & TCB_WAITEXECVE) {
1736		/* This is the post-execve SIGTRAP. */
1737		tcp->flags &= ~TCB_WAITEXECVE;
1738		return 0;
1739	}
1740#endif
1741
1742	scno_good = res = (get_regs_error ? -1 : get_scno(tcp));
1743	if (res == 0)
1744		return res;
1745	if (res == 1) {
1746		res = syscall_fixup_on_sysenter(tcp);
1747		if (res == 0)
1748			return res;
1749		if (res == 1)
1750			res = get_syscall_args(tcp);
1751	}
1752
1753	if (res != 1) {
1754		printleader(tcp);
1755		if (scno_good != 1)
1756			tprints("????" /* anti-trigraph gap */ "(");
1757		else if (!SCNO_IN_RANGE(tcp->scno))
1758			tprintf("syscall_%lu(", tcp->scno);
1759		else
1760			tprintf("%s(", sysent[tcp->scno].sys_name);
1761		/*
1762		 * " <unavailable>" will be added later by the code which
1763		 * detects ptrace errors.
1764		 */
1765		goto ret;
1766	}
1767
1768#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
1769	while (SCNO_IN_RANGE(tcp->scno)) {
1770# ifdef SYS_socket_subcall
1771		if (sysent[tcp->scno].sys_func == sys_socketcall) {
1772			decode_socket_subcall(tcp);
1773			break;
1774		}
1775# endif
1776# ifdef SYS_ipc_subcall
1777		if (sysent[tcp->scno].sys_func == sys_ipc) {
1778			decode_ipc_subcall(tcp);
1779			break;
1780		}
1781# endif
1782		break;
1783	}
1784#endif /* SYS_socket_subcall || SYS_ipc_subcall */
1785
1786	if (need_fork_exec_workarounds)
1787		syscall_fixup_for_fork_exec(tcp);
1788
1789	if ((SCNO_IN_RANGE(tcp->scno) &&
1790	     !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
1791	    (tracing_paths && !pathtrace_match(tcp))) {
1792		tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
1793		return 0;
1794	}
1795
1796	tcp->flags &= ~TCB_FILTERED;
1797
1798	if (cflag == CFLAG_ONLY_STATS) {
1799		res = 0;
1800		goto ret;
1801	}
1802
1803	printleader(tcp);
1804	if (!SCNO_IN_RANGE(tcp->scno))
1805		tprintf("syscall_%lu(", tcp->scno);
1806	else
1807		tprintf("%s(", sysent[tcp->scno].sys_name);
1808	if (!SCNO_IN_RANGE(tcp->scno) ||
1809	    ((qual_flags[tcp->scno] & QUAL_RAW) &&
1810	     sysent[tcp->scno].sys_func != sys_exit))
1811		res = printargs(tcp);
1812	else
1813		res = (*sysent[tcp->scno].sys_func)(tcp);
1814
1815	fflush(tcp->outf);
1816 ret:
1817	tcp->flags |= TCB_INSYSCALL;
1818	/* Measure the entrance time as late as possible to avoid errors. */
1819	if (Tflag || cflag)
1820		gettimeofday(&tcp->etime, NULL);
1821	return res;
1822}
1823
1824/* Returns:
1825 * 1: ok, continue in trace_syscall_exiting().
1826 * -1: error, trace_syscall_exiting() should print error indicator
1827 *    ("????" etc) and bail out.
1828 */
1829static int
1830get_syscall_result(struct tcb *tcp)
1831{
1832#if defined(S390) || defined(S390X)
1833	if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1834		return -1;
1835#elif defined(POWERPC)
1836# define SO_MASK 0x10000000
1837	{
1838		long flags;
1839		if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1840			return -1;
1841		if (upeek(tcp, sizeof(unsigned long)*PT_R3, &ppc_result) < 0)
1842			return -1;
1843		if (flags & SO_MASK)
1844			ppc_result = -ppc_result;
1845	}
1846#elif defined(AVR32)
1847	/* already done by get_regs */
1848#elif defined(BFIN)
1849	if (upeek(tcp, PT_R0, &r0) < 0)
1850		return -1;
1851#elif defined(I386)
1852	/* already done by get_regs */
1853#elif defined(X86_64) || defined(X32)
1854	/* already done by get_regs */
1855#elif defined(IA64)
1856#	define IA64_PSR_IS	((long)1 << 34)
1857	long psr;
1858	if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
1859		ia32 = (psr & IA64_PSR_IS) != 0;
1860	if (upeek(tcp, PT_R8, &r8) < 0)
1861		return -1;
1862	if (upeek(tcp, PT_R10, &r10) < 0)
1863		return -1;
1864#elif defined(AARCH64)
1865/* FIXME: uh, why do we do it on syscall *exit*? We did it on entry already... */
1866	/* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
1867	 * else it's personality 0.
1868	 */
1869	update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));
1870#elif defined(ARM)
1871	/* already done by get_regs */
1872#elif defined(M68K)
1873	if (upeek(tcp, 4*PT_D0, &d0) < 0)
1874		return -1;
1875#elif defined(LINUX_MIPSN32)
1876	unsigned long long regs[38];
1877
1878	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1879		return -1;
1880	a3 = regs[REG_A3];
1881	r2 = regs[REG_V0];
1882#elif defined(MIPS)
1883	if (upeek(tcp, REG_A3, &a3) < 0)
1884		return -1;
1885	if (upeek(tcp, REG_V0, &r2) < 0)
1886		return -1;
1887#elif defined(ALPHA)
1888	if (upeek(tcp, REG_A3, &a3) < 0)
1889		return -1;
1890	if (upeek(tcp, REG_R0, &r0) < 0)
1891		return -1;
1892#elif defined(SPARC) || defined(SPARC64)
1893	/* already done by get_regs */
1894#elif defined(HPPA)
1895	if (upeek(tcp, PT_GR28, &r28) < 0)
1896		return -1;
1897#elif defined(SH)
1898	/* new syscall ABI returns result in R0 */
1899	if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1900		return -1;
1901#elif defined(SH64)
1902	/* ABI defines result returned in r9 */
1903	if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1904		return -1;
1905#elif defined(CRISV10) || defined(CRISV32)
1906	if (upeek(tcp, 4*PT_R10, &r10) < 0)
1907		return -1;
1908#elif defined(TILE)
1909	/* already done by get_regs */
1910#elif defined(MICROBLAZE)
1911	if (upeek(tcp, 3 * 4, &r3) < 0)
1912		return -1;
1913#endif
1914	return 1;
1915}
1916
1917/* Called at each syscall exit */
1918static void
1919syscall_fixup_on_sysexit(struct tcb *tcp)
1920{
1921#if defined(S390) || defined(S390X)
1922	if (syscall_mode != -ENOSYS)
1923		syscall_mode = tcp->scno;
1924	if ((tcp->flags & TCB_WAITEXECVE)
1925		 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1926		/*
1927		 * Return from execve.
1928		 * Fake a return value of zero.  We leave the TCB_WAITEXECVE
1929		 * flag set for the post-execve SIGTRAP to see and reset.
1930		 */
1931		gpr2 = 0;
1932	}
1933#endif
1934}
1935
1936/*
1937 * Check the syscall return value register value for whether it is
1938 * a negated errno code indicating an error, or a success return value.
1939 */
1940static inline int
1941is_negated_errno(unsigned long int val)
1942{
1943	unsigned long int max = -(long int) nerrnos;
1944#if SUPPORTED_PERSONALITIES > 1
1945	if (current_wordsize < sizeof(val)) {
1946		val = (unsigned int) val;
1947		max = (unsigned int) max;
1948	}
1949#endif
1950	return val > max;
1951}
1952
1953/* Returns:
1954 * 1: ok, continue in trace_syscall_exiting().
1955 * -1: error, trace_syscall_exiting() should print error indicator
1956 *    ("????" etc) and bail out.
1957 */
1958static int
1959get_error(struct tcb *tcp)
1960{
1961	int u_error = 0;
1962	int check_errno = 1;
1963	if (SCNO_IN_RANGE(tcp->scno) &&
1964	    sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) {
1965		check_errno = 0;
1966	}
1967#if defined(S390) || defined(S390X)
1968	if (check_errno && is_negated_errno(gpr2)) {
1969		tcp->u_rval = -1;
1970		u_error = -gpr2;
1971	}
1972	else {
1973		tcp->u_rval = gpr2;
1974	}
1975#elif defined(I386)
1976	if (check_errno && is_negated_errno(i386_regs.eax)) {
1977		tcp->u_rval = -1;
1978		u_error = -i386_regs.eax;
1979	}
1980	else {
1981		tcp->u_rval = i386_regs.eax;
1982	}
1983#elif defined(X86_64) || defined(X32)
1984	if (check_errno && is_negated_errno(x86_64_regs.rax)) {
1985		tcp->u_rval = -1;
1986		u_error = -x86_64_regs.rax;
1987	}
1988	else {
1989		tcp->u_rval = x86_64_regs.rax;
1990# if defined(X32)
1991		tcp->u_lrval = x86_64_regs.rax;
1992# endif
1993	}
1994#elif defined(IA64)
1995	if (ia32) {
1996		int err;
1997
1998		err = (int)r8;
1999		if (check_errno && is_negated_errno(err)) {
2000			tcp->u_rval = -1;
2001			u_error = -err;
2002		}
2003		else {
2004			tcp->u_rval = err;
2005		}
2006	} else {
2007		if (check_errno && r10) {
2008			tcp->u_rval = -1;
2009			u_error = r8;
2010		} else {
2011			tcp->u_rval = r8;
2012		}
2013	}
2014#elif defined(MIPS)
2015	if (check_errno && a3) {
2016		tcp->u_rval = -1;
2017		u_error = r2;
2018	} else {
2019		tcp->u_rval = r2;
2020# if defined(LINUX_MIPSN32)
2021		tcp->u_lrval = r2;
2022# endif
2023	}
2024#elif defined(POWERPC)
2025	if (check_errno && is_negated_errno(ppc_result)) {
2026		tcp->u_rval = -1;
2027		u_error = -ppc_result;
2028	}
2029	else {
2030		tcp->u_rval = ppc_result;
2031	}
2032#elif defined(M68K)
2033	if (check_errno && is_negated_errno(d0)) {
2034		tcp->u_rval = -1;
2035		u_error = -d0;
2036	}
2037	else {
2038		tcp->u_rval = d0;
2039	}
2040#elif defined(ARM) || defined(AARCH64)
2041# if defined(AARCH64)
2042	if (tcp->currpers == 1) {
2043		if (check_errno && is_negated_errno(aarch64_regs.regs[0])) {
2044			tcp->u_rval = -1;
2045			u_error = -aarch64_regs.regs[0];
2046		}
2047		else {
2048			tcp->u_rval = aarch64_regs.regs[0];
2049		}
2050	}
2051	else
2052# endif /* AARCH64 */
2053	{
2054		if (check_errno && is_negated_errno(regs.ARM_r0)) {
2055			tcp->u_rval = -1;
2056			u_error = -regs.ARM_r0;
2057		}
2058		else {
2059			tcp->u_rval = regs.ARM_r0;
2060		}
2061	}
2062#elif defined(AVR32)
2063	if (check_errno && regs.r12 && (unsigned) -regs.r12 < nerrnos) {
2064		tcp->u_rval = -1;
2065		u_error = -regs.r12;
2066	}
2067	else {
2068		tcp->u_rval = regs.r12;
2069	}
2070#elif defined(BFIN)
2071	if (check_errno && is_negated_errno(r0)) {
2072		tcp->u_rval = -1;
2073		u_error = -r0;
2074	} else {
2075		tcp->u_rval = r0;
2076	}
2077#elif defined(ALPHA)
2078	if (check_errno && a3) {
2079		tcp->u_rval = -1;
2080		u_error = r0;
2081	}
2082	else {
2083		tcp->u_rval = r0;
2084	}
2085#elif defined(SPARC)
2086	if (check_errno && regs.psr & PSR_C) {
2087		tcp->u_rval = -1;
2088		u_error = regs.u_regs[U_REG_O0];
2089	}
2090	else {
2091		tcp->u_rval = regs.u_regs[U_REG_O0];
2092	}
2093#elif defined(SPARC64)
2094	if (check_errno && regs.tstate & 0x1100000000UL) {
2095		tcp->u_rval = -1;
2096		u_error = regs.u_regs[U_REG_O0];
2097	}
2098	else {
2099		tcp->u_rval = regs.u_regs[U_REG_O0];
2100	}
2101#elif defined(HPPA)
2102	if (check_errno && is_negated_errno(r28)) {
2103		tcp->u_rval = -1;
2104		u_error = -r28;
2105	}
2106	else {
2107		tcp->u_rval = r28;
2108	}
2109#elif defined(SH)
2110	if (check_errno && is_negated_errno(r0)) {
2111		tcp->u_rval = -1;
2112		u_error = -r0;
2113	}
2114	else {
2115		tcp->u_rval = r0;
2116	}
2117#elif defined(SH64)
2118	if (check_errno && is_negated_errno(r9)) {
2119		tcp->u_rval = -1;
2120		u_error = -r9;
2121	}
2122	else {
2123		tcp->u_rval = r9;
2124	}
2125#elif defined(CRISV10) || defined(CRISV32)
2126	if (check_errno && r10 && (unsigned) -r10 < nerrnos) {
2127		tcp->u_rval = -1;
2128		u_error = -r10;
2129	}
2130	else {
2131		tcp->u_rval = r10;
2132	}
2133#elif defined(TILE)
2134	/*
2135	 * The standard tile calling convention returns the value (or negative
2136	 * errno) in r0, and zero (or positive errno) in r1.
2137	 * Until at least kernel 3.8, however, the r1 value is not reflected
2138	 * in ptregs at this point, so we use r0 here.
2139	 */
2140	if (check_errno && is_negated_errno(tile_regs.regs[0])) {
2141		tcp->u_rval = -1;
2142		u_error = -tile_regs.regs[0];
2143	} else {
2144		tcp->u_rval = tile_regs.regs[0];
2145	}
2146#elif defined(MICROBLAZE)
2147	if (check_errno && is_negated_errno(r3)) {
2148		tcp->u_rval = -1;
2149		u_error = -r3;
2150	}
2151	else {
2152		tcp->u_rval = r3;
2153	}
2154#endif
2155	tcp->u_error = u_error;
2156	return 1;
2157}
2158
2159static void
2160dumpio(struct tcb *tcp)
2161{
2162	if (syserror(tcp))
2163		return;
2164	if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
2165		return;
2166	if (!SCNO_IN_RANGE(tcp->scno))
2167		return;
2168	if (sysent[tcp->scno].sys_func == printargs)
2169		return;
2170	if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
2171		if (sysent[tcp->scno].sys_func == sys_read ||
2172		    sysent[tcp->scno].sys_func == sys_pread ||
2173		    sysent[tcp->scno].sys_func == sys_recv ||
2174		    sysent[tcp->scno].sys_func == sys_recvfrom)
2175			dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
2176		else if (sysent[tcp->scno].sys_func == sys_readv)
2177			dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2178		return;
2179	}
2180	if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
2181		if (sysent[tcp->scno].sys_func == sys_write ||
2182		    sysent[tcp->scno].sys_func == sys_pwrite ||
2183		    sysent[tcp->scno].sys_func == sys_send ||
2184		    sysent[tcp->scno].sys_func == sys_sendto)
2185			dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
2186		else if (sysent[tcp->scno].sys_func == sys_writev)
2187			dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
2188		return;
2189	}
2190}
2191
2192static int
2193trace_syscall_exiting(struct tcb *tcp)
2194{
2195	int sys_res;
2196	struct timeval tv;
2197	int res;
2198	long u_error;
2199
2200	/* Measure the exit time as early as possible to avoid errors. */
2201	if (Tflag || cflag)
2202		gettimeofday(&tv, NULL);
2203
2204#if SUPPORTED_PERSONALITIES > 1
2205	update_personality(tcp, tcp->currpers);
2206#endif
2207	res = (get_regs_error ? -1 : get_syscall_result(tcp));
2208	if (res == 1) {
2209		syscall_fixup_on_sysexit(tcp); /* never fails */
2210		res = get_error(tcp); /* returns 1 or -1 */
2211		if (res == 1) {
2212			if (need_fork_exec_workarounds)
2213				syscall_fixup_for_fork_exec(tcp);
2214			if (filtered(tcp)) {
2215				goto ret;
2216			}
2217		}
2218	}
2219
2220	if (cflag) {
2221		struct timeval t = tv;
2222		count_syscall(tcp, &t);
2223		if (cflag == CFLAG_ONLY_STATS) {
2224			goto ret;
2225		}
2226	}
2227
2228	/* If not in -ff mode, and printing_tcp != tcp,
2229	 * then the log currently does not end with output
2230	 * of _our syscall entry_, but with something else.
2231	 * We need to say which syscall's return is this.
2232	 *
2233	 * Forced reprinting via TCB_REPRINT is used only by
2234	 * "strace -ff -oLOG test/threaded_execve" corner case.
2235	 * It's the only case when -ff mode needs reprinting.
2236	 */
2237	if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
2238		tcp->flags &= ~TCB_REPRINT;
2239		printleader(tcp);
2240		if (!SCNO_IN_RANGE(tcp->scno))
2241			tprintf("<... syscall_%lu resumed> ", tcp->scno);
2242		else
2243			tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
2244	}
2245	printing_tcp = tcp;
2246
2247	if (res != 1) {
2248		/* There was error in one of prior ptrace ops */
2249		tprints(") ");
2250		tabto();
2251		tprints("= ? <unavailable>\n");
2252		line_ended();
2253		tcp->flags &= ~TCB_INSYSCALL;
2254		return res;
2255	}
2256
2257	sys_res = 0;
2258	if (!SCNO_IN_RANGE(tcp->scno)
2259	    || (qual_flags[tcp->scno] & QUAL_RAW)) {
2260		/* sys_res = printargs(tcp); - but it's nop on sysexit */
2261	} else {
2262	/* FIXME: not_failing_only (IOW, option -z) is broken:
2263	 * failure of syscall is known only after syscall return.
2264	 * Thus we end up with something like this on, say, ENOENT:
2265	 *     open("doesnt_exist", O_RDONLY <unfinished ...>
2266	 *     {next syscall decode}
2267	 * whereas the intended result is that open(...) line
2268	 * is not shown at all.
2269	 */
2270		if (not_failing_only && tcp->u_error)
2271			goto ret;	/* ignore failed syscalls */
2272		sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2273	}
2274
2275	tprints(") ");
2276	tabto();
2277	u_error = tcp->u_error;
2278	if (!SCNO_IN_RANGE(tcp->scno) ||
2279	    qual_flags[tcp->scno] & QUAL_RAW) {
2280		if (u_error)
2281			tprintf("= -1 (errno %ld)", u_error);
2282		else
2283			tprintf("= %#lx", tcp->u_rval);
2284	}
2285	else if (!(sys_res & RVAL_NONE) && u_error) {
2286		switch (u_error) {
2287		/* Blocked signals do not interrupt any syscalls.
2288		 * In this case syscalls don't return ERESTARTfoo codes.
2289		 *
2290		 * Deadly signals set to SIG_DFL interrupt syscalls
2291		 * and kill the process regardless of which of the codes below
2292		 * is returned by the interrupted syscall.
2293		 * In some cases, kernel forces a kernel-generated deadly
2294		 * signal to be unblocked and set to SIG_DFL (and thus cause
2295		 * death) if it is blocked or SIG_IGNed: for example, SIGSEGV
2296		 * or SIGILL. (The alternative is to leave process spinning
2297		 * forever on the faulty instruction - not useful).
2298		 *
2299		 * SIG_IGNed signals and non-deadly signals set to SIG_DFL
2300		 * (for example, SIGCHLD, SIGWINCH) interrupt syscalls,
2301		 * but kernel will always restart them.
2302		 */
2303		case ERESTARTSYS:
2304			/* Most common type of signal-interrupted syscall exit code.
2305			 * The system call will be restarted with the same arguments
2306			 * if SA_RESTART is set; otherwise, it will fail with EINTR.
2307			 */
2308			tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)");
2309			break;
2310		case ERESTARTNOINTR:
2311			/* Rare. For example, fork() returns this if interrupted.
2312			 * SA_RESTART is ignored (assumed set): the restart is unconditional.
2313			 */
2314			tprints("= ? ERESTARTNOINTR (To be restarted)");
2315			break;
2316		case ERESTARTNOHAND:
2317			/* pause(), rt_sigsuspend() etc use this code.
2318			 * SA_RESTART is ignored (assumed not set):
2319			 * syscall won't restart (will return EINTR instead)
2320			 * even after signal with SA_RESTART set.
2321			 * However, after SIG_IGN or SIG_DFL signal it will.
2322			 */
2323			tprints("= ? ERESTARTNOHAND (Interrupted by signal)");
2324			break;
2325		case ERESTART_RESTARTBLOCK:
2326			/* Syscalls like nanosleep(), poll() which can't be
2327			 * restarted with their original arguments use this
2328			 * code. Kernel will execute restart_syscall() instead,
2329			 * which changes arguments before restarting syscall.
2330			 * SA_RESTART is ignored (assumed not set) similarly
2331			 * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART
2332			 * since restart data is saved in "restart block"
2333			 * in task struct, and if signal handler uses a syscall
2334			 * which in turn saves another such restart block,
2335			 * old data is lost and restart becomes impossible)
2336			 */
2337			tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
2338			break;
2339		default:
2340			if (u_error < 0)
2341				tprintf("= -1 E??? (errno %ld)", u_error);
2342			else if (u_error < nerrnos)
2343				tprintf("= -1 %s (%s)", errnoent[u_error],
2344					strerror(u_error));
2345			else
2346				tprintf("= -1 ERRNO_%ld (%s)", u_error,
2347					strerror(u_error));
2348			break;
2349		}
2350		if ((sys_res & RVAL_STR) && tcp->auxstr)
2351			tprintf(" (%s)", tcp->auxstr);
2352	}
2353	else {
2354		if (sys_res & RVAL_NONE)
2355			tprints("= ?");
2356		else {
2357			switch (sys_res & RVAL_MASK) {
2358			case RVAL_HEX:
2359				tprintf("= %#lx", tcp->u_rval);
2360				break;
2361			case RVAL_OCTAL:
2362				tprintf("= %#lo", tcp->u_rval);
2363				break;
2364			case RVAL_UDECIMAL:
2365				tprintf("= %lu", tcp->u_rval);
2366				break;
2367			case RVAL_DECIMAL:
2368				tprintf("= %ld", tcp->u_rval);
2369				break;
2370#if defined(LINUX_MIPSN32) || defined(X32)
2371			/*
2372			case RVAL_LHEX:
2373				tprintf("= %#llx", tcp->u_lrval);
2374				break;
2375			case RVAL_LOCTAL:
2376				tprintf("= %#llo", tcp->u_lrval);
2377				break;
2378			*/
2379			case RVAL_LUDECIMAL:
2380				tprintf("= %llu", tcp->u_lrval);
2381				break;
2382			/*
2383			case RVAL_LDECIMAL:
2384				tprintf("= %lld", tcp->u_lrval);
2385				break;
2386			*/
2387#endif
2388			default:
2389				fprintf(stderr,
2390					"invalid rval format\n");
2391				break;
2392			}
2393		}
2394		if ((sys_res & RVAL_STR) && tcp->auxstr)
2395			tprintf(" (%s)", tcp->auxstr);
2396	}
2397	if (Tflag) {
2398		tv_sub(&tv, &tv, &tcp->etime);
2399		tprintf(" <%ld.%06ld>",
2400			(long) tv.tv_sec, (long) tv.tv_usec);
2401	}
2402	tprints("\n");
2403	dumpio(tcp);
2404	line_ended();
2405
2406 ret:
2407	tcp->flags &= ~TCB_INSYSCALL;
2408	return 0;
2409}
2410
2411int
2412trace_syscall(struct tcb *tcp)
2413{
2414	return exiting(tcp) ?
2415		trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2416}
2417