# endif
#endif
-/* configuration section */
+/* Configuration section */
#ifndef MAX_QUALS
#if defined(LINUX) && defined(MIPS)
#define MAX_QUALS 7000 /* maximum number of syscalls, signals, etc. */
#endif
#endif
#ifndef DEFAULT_STRLEN
-#define DEFAULT_STRLEN 32 /* default maximum # of bytes printed in
- `printstr', change with `-s' switch */
+/* default maximum # of bytes printed in `printstr', change with -s switch */
+#define DEFAULT_STRLEN 32
#endif
#ifndef DEFAULT_ACOLUMN
#define DEFAULT_ACOLUMN 40 /* default alignment column for results */
#endif
+
+/* Maximum number of args to a syscall.
+ *
+ * Make sure that all entries in all syscallent.h files
+ * have nargs <= MAX_ARGS!
+ * linux/<ARCH>/syscallent.h: all have nargs <= 6.
+ * freebsd/i386/syscallent.h: one syscall with nargs = 8
+ * (sys_sendfile, looks legitimate)
+ * and one with nargs = 7 (sys_mmap, maybe it should have 6?).
+ * sunos4/syscallent.h: all are <= 6.
+ * svr4/syscallent.h: all are MA (MAX_ARGS), it's unclear what the real max is.
+ */
#ifndef MAX_ARGS
-#define MAX_ARGS 32 /* maximum number of args to a syscall */
+# if defined LINUX
+# define MAX_ARGS 6
+# elif defined HPPA
+# define MAX_ARGS 6
+# elif defined X86_64 || defined I386
+# ifdef FREEBSD
+# define MAX_ARGS 8
+# else
+# define MAX_ARGS 6
+# endif
+# else
+/* Way too big. Switch your arch to saner size after you tested that it works */
+# define MAX_ARGS 32
+# endif
#endif
+
#ifndef DEFAULT_SORTBY
#define DEFAULT_SORTBY "time" /* default sorting method for call profiling */
#endif
# if defined(SPARC) || defined(SPARC64)
# define LINUXSPARC
# endif
-# if defined(ALPHA)
-# define LINUX_64BIT
-# endif
# if defined(X86_64)
# define LINUX_X86_64
# endif
# define LINUX_MIPSN64
# define LINUX_MIPS64
# endif
+# if defined(ARM)
+# define LINUX_ARM
+# endif
+# if defined(AVR32)
+# define LINUX_AVR32
+# endif
#endif
#if defined(SVR4) || defined(FREEBSD)
#endif
#ifdef USE_PROCFS
-#include <sys/procfs.h>
-#ifdef HAVE_MP_PROCFS
-#include <sys/uio.h>
-#endif
-#ifdef FREEBSD
-#include <sys/pioctl.h>
-#endif /* FREEBSD */
+# include <sys/procfs.h>
+# ifdef HAVE_MP_PROCFS
+# include <sys/uio.h>
+# endif
+# ifdef FREEBSD
+# include <sys/pioctl.h>
+# endif
#else /* !USE_PROCFS */
-#if (defined(LINUXSPARC) || defined (LINUX_X86_64)) && defined(__GLIBC__)
-#include <sys/ptrace.h>
-#else
+# if (defined(LINUXSPARC) || defined(LINUX_X86_64) || defined(LINUX_ARM) || defined(LINUX_AVR32)) && defined(__GLIBC__)
+# include <sys/ptrace.h>
+# else
/* Work around awkward prototype in ptrace.h. */
-#define ptrace xptrace
-#include <sys/ptrace.h>
-#undef ptrace
-#ifdef POWERPC
-#define __KERNEL__
-#include <asm/ptrace.h>
-#undef __KERNEL__
-#endif
-#ifdef __STDC__
-#ifdef LINUX
+# define ptrace xptrace
+# include <sys/ptrace.h>
+# undef ptrace
+# ifdef POWERPC
+# define __KERNEL__
+# include <asm/ptrace.h>
+# undef __KERNEL__
+# endif
+# ifdef LINUX
extern long ptrace(int, int, char *, long);
-#else /* !LINUX */
+# else
extern int ptrace(int, int, char *, int, ...);
-#endif /* !LINUX */
-#else /* !__STDC__ */
-extern int ptrace();
-#endif /* !__STDC__ */
-#endif /* !LINUXSPARC */
-#endif /* !SVR4 */
+# endif
+# endif
+#endif /* !USE_PROCFS */
#ifdef LINUX
#if !defined(__GLIBC__)
#define PTRACE_PEEKUSER PTRACE_PEEKUSR
#define PTRACE_POKEUSER PTRACE_POKEUSR
#endif
+#if defined(X86_64) || defined(I386)
+/* For struct pt_regs. x86 strace uses PTRACE_GETREGS.
+ * PTRACE_GETREGS returns registers in the layout of this struct.
+ */
+# include <asm/ptrace.h>
+#endif
#ifdef ALPHA
# define REG_R0 0
# define REG_A0 16
#define DEFAULT_PERSONALITY 0
#ifdef LINUXSPARC
+/* Indexes into the pt_regs.u_reg[] array -- UREG_XX from kernel are all off
+ * by 1 and use Ix instead of Ox. These work for both 32 and 64 bit Linux. */
+#define U_REG_G1 0
+#define U_REG_O0 7
+#define U_REG_O1 8
#define PERSONALITY0_WORDSIZE 4
#define PERSONALITY1_WORDSIZE 4
#undef SUPPORTED_PERSONALITIES
#define PERSONALITY1_WORDSIZE 4
#endif
+#ifdef POWERPC64
+#undef SUPPORTED_PERSONALITIES
+#define SUPPORTED_PERSONALITIES 2
+#define PERSONALITY0_WORDSIZE 8
+#define PERSONALITY1_WORDSIZE 4
+#endif
+
#ifdef SVR4
#ifdef HAVE_MP_PROCFS
-extern int mp_ioctl (int f, int c, void *a, int s);
-#define IOCTL(f,c,a) mp_ioctl (f, c, a, sizeof *a)
+extern int mp_ioctl(int f, int c, void *a, int s);
+#define IOCTL(f,c,a) mp_ioctl(f, c, a, sizeof *a)
#define IOCTL_STATUS(t) \
- pread (t->pfd_stat, &t->status, sizeof t->status, 0)
-#define IOCTL_WSTOP(t) \
- (IOCTL (t->pfd, PCWSTOP, (char *)NULL) < 0 ? -1 : \
- IOCTL_STATUS (t))
+ pread(t->pfd_stat, &t->status, sizeof t->status, 0)
+#define IOCTL_WSTOP(t) \
+ (IOCTL(t->pfd, PCWSTOP, (char *)NULL) < 0 ? -1 : IOCTL_STATUS(t))
#define PR_WHY pr_lwp.pr_why
#define PR_WHAT pr_lwp.pr_what
#define PR_REG pr_lwp.pr_context.uc_mcontext.gregs
#define PIOCRUN PCRUN
#else
#define IOCTL ioctl
-#define IOCTL_STATUS(t) ioctl (t->pfd, PIOCSTATUS, &t->status)
-#define IOCTL_WSTOP(t) ioctl (t->pfd, PIOCWSTOP, &t->status)
+#define IOCTL_STATUS(t) ioctl(t->pfd, PIOCSTATUS, &t->status)
+#define IOCTL_WSTOP(t) ioctl(t->pfd, PIOCWSTOP, &t->status)
#define PR_WHY pr_why
#define PR_WHAT pr_what
#define PR_REG pr_reg
#endif
#ifdef FREEBSD
#define IOCTL ioctl
-#define IOCTL_STATUS(t) ioctl (t->pfd, PIOCSTATUS, &t->status)
-#define IOCTL_WSTOP(t) ioctl (t->pfd, PIOCWAIT, &t->status)
+#define IOCTL_STATUS(t) ioctl(t->pfd, PIOCSTATUS, &t->status)
+#define IOCTL_WSTOP(t) ioctl(t->pfd, PIOCWAIT, &t->status)
#define PIOCRUN PIOCCONT
#define PIOCWSTOP PIOCWAIT
#define PR_WHY why
#define PR_FAULTED S_CORE
#endif
+#ifdef LINUX
+# if !HAVE_DECL_PTRACE_SETOPTIONS
+# define PTRACE_SETOPTIONS 0x4200
+# endif
+# if !HAVE_DECL_PTRACE_GETEVENTMSG
+# define PTRACE_GETEVENTMSG 0x4201
+# endif
+# if !HAVE_DECL_PTRACE_GETSIGINFO
+# define PTRACE_GETSIGINFO 0x4202
+# endif
+
+# if !HAVE_DECL_PTRACE_O_TRACESYSGOOD
+# define PTRACE_O_TRACESYSGOOD 0x00000001
+# endif
+# if !HAVE_DECL_PTRACE_O_TRACEFORK
+# define PTRACE_O_TRACEFORK 0x00000002
+# endif
+# if !HAVE_DECL_PTRACE_O_TRACEVFORK
+# define PTRACE_O_TRACEVFORK 0x00000004
+# endif
+# if !HAVE_DECL_PTRACE_O_TRACECLONE
+# define PTRACE_O_TRACECLONE 0x00000008
+# endif
+# if !HAVE_DECL_PTRACE_O_TRACEEXEC
+# define PTRACE_O_TRACEEXEC 0x00000010
+# endif
+# if !HAVE_DECL_PTRACE_O_TRACEEXIT
+# define PTRACE_O_TRACEEXIT 0x00000040
+# endif
+
+# if !HAVE_DECL_PTRACE_EVENT_FORK
+# define PTRACE_EVENT_FORK 1
+# endif
+# if !HAVE_DECL_PTRACE_EVENT_VFORK
+# define PTRACE_EVENT_VFORK 2
+# endif
+# if !HAVE_DECL_PTRACE_EVENT_CLONE
+# define PTRACE_EVENT_CLONE 3
+# endif
+# if !HAVE_DECL_PTRACE_EVENT_EXEC
+# define PTRACE_EVENT_EXEC 4
+# endif
+# if !HAVE_DECL_PTRACE_EVENT_VFORK_DONE
+# define PTRACE_EVENT_VFORK_DONE 5
+# endif
+# if !HAVE_DECL_PTRACE_EVENT_EXIT
+# define PTRACE_EVENT_EXIT 6
+# endif
+#endif /* LINUX */
+
+#if !defined __GNUC__
+# define __attribute__(x) /*nothing*/
+#endif
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
/* Trace Control Block */
struct tcb {
- short flags; /* See below for TCB_ values */
+ int flags; /* See below for TCB_ values */
int pid; /* Process Id of this entry */
+ int u_nargs; /* System call argument count */
+ int u_error; /* Error code */
long scno; /* System call number */
- int u_nargs; /* System call arguments */
long u_arg[MAX_ARGS]; /* System call arguments */
#if defined (LINUX_MIPSN32)
long long ext_arg[MAX_ARGS]; /* System call arguments */
#endif
- int u_error; /* Error code */
long u_rval; /* (first) return value */
#ifdef HAVE_LONG_LONG
long long u_lrval; /* long long return value */
#endif
+ int ptrace_errno;
+ int curcol; /* Output column for this process */
FILE *outf; /* Output file for this process */
const char *auxstr; /* Auxiliary info from syscall (see RVAL_STR) */
struct timeval stime; /* System time usage as of last process wait */
struct timeval dtime; /* Delta for system time usage */
struct timeval etime; /* Syscall entry time */
/* Support for tracing forked processes */
- struct tcb *parent; /* Parent of this process */
- int nchildren; /* # of traced children */
- int waitpid; /* pid(s) this process is waiting for */
- int nzombies; /* # of formerly traced children now dead */
-#ifdef LINUX
- int nclone_threads; /* # of nchildren with CLONE_THREAD */
- int nclone_detached; /* # of nchildren with CLONE_DETACHED */
- int nclone_waiting; /* clone threads in wait4 (TCB_SUSPENDED) */
-#endif
- /* (1st arg of wait4()) */
long baddr; /* `Breakpoint' address */
long inst[2]; /* Instructions on above */
+#ifdef USE_PROCFS
int pfd; /* proc file descriptor */
+#endif
#ifdef SVR4
-#ifdef HAVE_MP_PROCFS
+# ifdef HAVE_MP_PROCFS
int pfd_stat;
int pfd_as;
pstatus_t status;
-#else
+# else
prstatus_t status; /* procfs status structure */
-#endif
+# endif
#endif
#ifdef FREEBSD
struct procfs_status status;
/* TCB flags */
#define TCB_STARTUP 00001 /* We have just begun ptracing this process */
#define TCB_INUSE 00002 /* This table entry is in use */
-#define TCB_INSYSCALL 00004 /* A system call is in progress */
+/*
+ * Are we in system call entry or in syscall exit?
+ *
+ * This bit is set after all syscall entry processing is done.
+ * Therefore, this bit will be set when next ptrace stop occurs,
+ * which should be syscall exit stop. Other stops which are possible
+ * directly after syscall entry (death, ptrace event stop)
+ * are simpler and handled without calling trace_syscall(), therefore
+ * the places where TCB_INSYSCALL can be set but we aren't in syscall stop
+ * are limited to trace(), this condition is never observed in trace_syscall()
+ * and below.
+ * The bit is cleared after all syscall exit processing is done.
+ * User-generated SIGTRAPs and post-execve SIGTRAP make it necessary
+ * to be very careful and NOT set TCB_INSYSCALL bit when they are encountered.
+ * TCB_WAITEXECVE bit is used for this purpose (see below).
+ *
+ * Use entering(tcp) / exiting(tcp) to check this bit to make code more readable.
+ */
+#define TCB_INSYSCALL 00004
#define TCB_ATTACHED 00010 /* Process is not our own child */
-#define TCB_EXITING 00020 /* As far as we know, this process is exiting */
-#define TCB_SUSPENDED 00040 /* Process has done a wait(4), that can
- not be allowed to complete just now */
+#ifdef LINUX
+#define TCB_ATTACH_DONE 00020 /* PTRACE_ATTACH was done on this tcb->pid */
+#endif
#define TCB_BPTSET 00100 /* "Breakpoint" set after fork(2) */
#define TCB_SIGTRAPPED 00200 /* Process wanted to block SIGTRAP */
-#define TCB_FOLLOWFORK 00400 /* Process should have forks followed */
#define TCB_REPRINT 01000 /* We should reprint this syscall on exit */
+#define TCB_FILTERED 02000 /* This system call has been filtered out */
#ifdef LINUX
-# if defined(ALPHA) || defined(SPARC) || defined(SPARC64) || defined(POWERPC) || defined(IA64) || defined(HPPA) || defined(SH) || defined(SH64) || defined(S390) || defined(S390X) || defined(ARM) || defined(MIPS) || defined(BFIN)
-# define TCB_WAITEXECVE 02000 /* ignore SIGTRAP after exceve */
+/* x86 does not need TCB_WAITEXECVE.
+ * It can detect SIGTRAP by looking at eax/rax.
+ * See "not a syscall entry (eax = %ld)\n" message
+ * in syscall_fixup_on_sysenter().
+ */
+# if defined(ALPHA) || defined(AVR32) || defined(SPARC) || defined(SPARC64) \
+ || defined(POWERPC) || defined(IA64) || defined(HPPA) \
+ || defined(SH) || defined(SH64) || defined(S390) || defined(S390X) \
+ || defined(ARM) || defined(MIPS) || defined(BFIN) || defined(TILE)
+/* This tracee has entered into execve syscall. Expect post-execve SIGTRAP
+ * to happen. (When it is detected, tracee is continued and this bit is cleared.)
+ */
+# define TCB_WAITEXECVE 04000
# endif
-# define TCB_CLONE_DETACHED 04000 /* CLONE_DETACHED set in creating syscall */
-# define TCB_CLONE_THREAD 010000 /* CLONE_THREAD set in creating syscall */
-# define TCB_GROUP_EXITING 020000 /* TCB_EXITING was exit_group, not _exit */
# include <sys/syscall.h>
# ifndef __NR_exit_group
# /* Hack: Most headers around are too old to have __NR_exit_group. */
#define syserror(tcp) ((tcp)->u_error != 0)
#define verbose(tcp) (qual_flags[(tcp)->scno] & QUAL_VERBOSE)
#define abbrev(tcp) (qual_flags[(tcp)->scno] & QUAL_ABBREV)
+#define filtered(tcp) ((tcp)->flags & TCB_FILTERED)
struct xlat {
int val;
- char *str;
+ const char *str;
};
+extern const struct xlat open_mode_flags[];
+extern const struct xlat addrfams[];
+extern const struct xlat struct_user_offsets[];
+extern const struct xlat open_access_modes[];
+
/* Format of syscall return values */
#define RVAL_DECIMAL 000 /* decimal format */
#define RVAL_HEX 001 /* hex format */
#define TRACE_PROCESS 010 /* Trace process-related syscalls. */
#define TRACE_SIGNAL 020 /* Trace signal-related syscalls. */
#define TRACE_DESC 040 /* Trace file descriptor-related syscalls. */
+#define SYSCALL_NEVER_FAILS 0100 /* Syscall is always successful. */
+
+typedef enum {
+ CFLAG_NONE = 0,
+ CFLAG_ONLY_STATS,
+ CFLAG_BOTH
+} cflag_t;
-extern struct tcb **tcbtab;
extern int *qual_flags;
extern int debug, followfork;
-extern int dtime, cflag, xflag, qflag;
-extern int acolumn;
-extern unsigned int nprocs, tcbtabsize;
+extern unsigned int ptrace_setoptions;
+extern int dtime, xflag, qflag;
+extern cflag_t cflag;
extern int max_strlen;
extern struct tcb *tcp_last;
-#ifdef __STDC__
-#define P(args) args
-#else
-#define P(args) ()
-#endif
-
enum bitness_t { BITNESS_CURRENT = 0, BITNESS_32 };
-extern int set_personality P((int personality));
-extern const char *xlookup P((const struct xlat *, int));
-extern struct tcb *alloc_tcb P((int, int));
-extern struct tcb *pid2tcb P((int));
-extern void droptcb P((struct tcb *));
-extern int expand_tcbtab P((void));
+void error_msg(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
+void perror_msg(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
+void error_msg_and_die(const char *fmt, ...) __attribute__ ((noreturn, format(printf, 1, 2)));
+void perror_msg_and_die(const char *fmt, ...) __attribute__ ((noreturn, format(printf, 1, 2)));
+void die_out_of_memory(void) __attribute__ ((noreturn));
+
+extern void set_personality(int personality);
+extern const char *xlookup(const struct xlat *, int);
+extern struct tcb *alloc_tcb(int, int);
+extern struct tcb *pid2tcb(int);
+extern void droptcb(struct tcb *);
#define alloctcb(pid) alloc_tcb((pid), 1)
-extern void set_sortby P((char *));
-extern void set_overhead P((int));
-extern void qualify P((char *));
-extern int get_scno P((struct tcb *));
-extern long known_scno P((struct tcb *));
-extern int trace_syscall P((struct tcb *));
-extern int count_syscall P((struct tcb *, struct timeval *));
-extern void printxval P((const struct xlat *, int, const char *));
-extern int printargs P((struct tcb *));
-extern int addflags P((const struct xlat *, int));
-extern int printflags P((const struct xlat *, int, const char *));
-extern const char *sprintflags P((const char *, const struct xlat *, int));
-extern int umoven P((struct tcb *, long, int, char *));
-extern int umovestr P((struct tcb *, long, int, char *));
-extern int upeek P((struct tcb *, long, long *));
-extern void dumpiov P((struct tcb *, int, long));
-extern void dumpstr P((struct tcb *, long, int));
-extern void printstr P((struct tcb *, long, int));
-extern void printnum P((struct tcb *, long, char *));
-extern void printnum_int P((struct tcb *, long, char *));
-extern void printpath P((struct tcb *, long));
-extern void printpathn P((struct tcb *, long, int));
-extern void printtv_bitness P((struct tcb *, long, enum bitness_t, int));
-extern void sprinttv P((struct tcb *, long, enum bitness_t, char *));
-extern void print_timespec P((struct tcb *, long));
-extern void sprint_timespec P((char *, struct tcb *, long));
+extern void set_sortby(const char *);
+extern void set_overhead(int);
+extern void qualify(const char *);
+#ifdef USE_PROCFS
+extern int get_scno(struct tcb *);
+#endif
+extern long known_scno(struct tcb *);
+extern long do_ptrace(int request, struct tcb *tcp, void *addr, void *data);
+extern int ptrace_restart(int request, struct tcb *tcp, int sig);
+extern int trace_syscall(struct tcb *);
+extern void count_syscall(struct tcb *, struct timeval *);
+extern void printxval(const struct xlat *, int, const char *);
+extern int printargs(struct tcb *);
+extern void addflags(const struct xlat *, int);
+extern int printflags(const struct xlat *, int, const char *);
+extern const char *sprintflags(const char *, const struct xlat *, int);
+extern int umoven(struct tcb *, long, int, char *);
+extern int umovestr(struct tcb *, long, int, char *);
+extern int upeek(struct tcb *, long, long *);
+extern void dumpiov(struct tcb *, int, long);
+extern void dumpstr(struct tcb *, long, int);
+extern void printstr(struct tcb *, long, int);
+extern void printnum(struct tcb *, long, const char *);
+extern void printnum_int(struct tcb *, long, const char *);
+extern void printpath(struct tcb *, long);
+extern void printpathn(struct tcb *, long, int);
+extern void printtv_bitness(struct tcb *, long, enum bitness_t, int);
+extern char *sprinttv(struct tcb *, long, enum bitness_t, char *);
+extern void print_timespec(struct tcb *, long);
+extern void sprint_timespec(char *, struct tcb *, long);
#ifdef HAVE_SIGINFO_T
-extern void printsiginfo P((siginfo_t *, int));
-#endif
-extern void printsock P((struct tcb *, long, int));
-extern void print_sock_optmgmt P((struct tcb *, long, int));
-extern void printrusage P((struct tcb *, long));
-extern void printuid P((const char *, unsigned long));
-extern int clearbpt P((struct tcb *));
-extern int setbpt P((struct tcb *));
-extern int sigishandled P((struct tcb *, int));
-extern void printcall P((struct tcb *));
-extern const char *signame P((int));
-extern void print_sigset P((struct tcb *, long, int));
-extern void printsignal P((int));
-extern void printleader P((struct tcb *));
-extern void printtrailer P((struct tcb *));
-extern void tabto P((int));
-extern void call_summary P((FILE *));
-extern void tprint_iov P((struct tcb *, unsigned long, unsigned long));
-extern void tprint_open_modes P((struct tcb *, mode_t));
-extern int is_restart_error P((struct tcb *));
-
-#ifdef LINUX
-extern int internal_clone P((struct tcb *));
-#endif
-extern int internal_fork P((struct tcb *));
-extern int internal_exec P((struct tcb *));
-extern int internal_wait P((struct tcb *, int));
-extern int internal_exit P((struct tcb *));
-
-extern const struct ioctlent *ioctl_lookup P((long));
-extern const struct ioctlent *ioctl_next_match P((const struct ioctlent *));
-extern int ioctl_decode P((struct tcb *, long, long));
-extern int term_ioctl P((struct tcb *, long, long));
-extern int sock_ioctl P((struct tcb *, long, long));
-extern int proc_ioctl P((struct tcb *, int, int));
-extern int stream_ioctl P((struct tcb *, int, int));
+extern void printsiginfo(siginfo_t *, int);
+#endif
+extern const char *getfdpath(struct tcb *, int);
+extern void printfd(struct tcb *, int);
+extern void printsock(struct tcb *, long, int);
+extern void print_sock_optmgmt(struct tcb *, long, int);
+extern void printrusage(struct tcb *, long);
+#ifdef ALPHA
+extern void printrusage32(struct tcb *, long);
+#endif
+extern void printuid(const char *, unsigned long);
+extern int clearbpt(struct tcb *);
+/*
+ * On Linux, "setbpt" is a misnomer: we don't set a breakpoint
+ * (IOW: no poking in user's text segment),
+ * instead we change fork/vfork/clone into clone(CLONE_PTRACE).
+ * On newer kernels, we use PTRACE_O_TRACECLONE/TRACE[V]FORK instead.
+ */
+extern int setbpt(struct tcb *);
+extern void printcall(struct tcb *);
+extern const char *signame(int);
+extern void print_sigset(struct tcb *, long, int);
+extern void printsignal(int);
+extern void printleader(struct tcb *);
+extern void printtrailer(void);
+extern void tabto(void);
+extern void call_summary(FILE *);
+extern void tprint_iov(struct tcb *, unsigned long, unsigned long, int decode_iov);
+extern void tprint_open_modes(mode_t);
+extern const char *sprint_open_modes(mode_t);
+extern int is_restart_error(struct tcb *);
+
+extern int pathtrace_select(const char *);
+extern int pathtrace_match(struct tcb *);
+
+extern int change_syscall(struct tcb *, int);
+extern int internal_fork(struct tcb *);
+extern int internal_exec(struct tcb *);
+
+extern const struct ioctlent *ioctl_lookup(long);
+extern const struct ioctlent *ioctl_next_match(const struct ioctlent *);
+extern int ioctl_decode(struct tcb *, long, long);
+extern int term_ioctl(struct tcb *, long, long);
+extern int sock_ioctl(struct tcb *, long, long);
+extern int proc_ioctl(struct tcb *, int, int);
+extern int stream_ioctl(struct tcb *, int, int);
#ifdef LINUX
-extern int rtc_ioctl P((struct tcb *, long, long));
-extern int scsi_ioctl P((struct tcb *, long, long));
+extern int rtc_ioctl(struct tcb *, long, long);
+extern int scsi_ioctl(struct tcb *, long, long);
+extern int block_ioctl(struct tcb *, long, long);
#endif
-extern void tv_tv P((struct timeval *, int, int));
-extern int tv_nz P((struct timeval *));
-extern int tv_cmp P((struct timeval *, struct timeval *));
-extern double tv_float P((struct timeval *));
-extern void tv_add P((struct timeval *, struct timeval *, struct timeval *));
-extern void tv_sub P((struct timeval *, struct timeval *, struct timeval *));
-extern void tv_mul P((struct timeval *, struct timeval *, int));
-extern void tv_div P((struct timeval *, struct timeval *, int));
+extern int tv_nz(struct timeval *);
+extern int tv_cmp(struct timeval *, struct timeval *);
+extern double tv_float(struct timeval *);
+extern void tv_add(struct timeval *, struct timeval *, struct timeval *);
+extern void tv_sub(struct timeval *, struct timeval *, struct timeval *);
+extern void tv_mul(struct timeval *, struct timeval *, int);
+extern void tv_div(struct timeval *, struct timeval *, int);
+
+/* Some libc have stpcpy, some don't. Sigh...
+ * Roll our private implementation...
+ */
+#undef stpcpy
+#define stpcpy strace_stpcpy
+extern char *stpcpy(char *dst, const char *src);
#ifdef SUNOS4
-extern int fixvfork P((struct tcb *));
+extern int fixvfork(struct tcb *);
#endif
-#if !(defined(LINUX) && !defined(SPARC) && !defined(SPARC64) && !defined(IA64))
-extern long getrval2 P((struct tcb *));
+#if !(defined(LINUX) && !defined(SPARC) && !defined(SPARC64) && !defined(IA64) \
+ && !defined(SH))
+extern long getrval2(struct tcb *);
#endif
#ifdef USE_PROCFS
-extern int proc_open P((struct tcb *tcp, int attaching));
+extern int proc_open(struct tcb *tcp, int attaching);
#endif
#define umove(pid, addr, objp) \
#define printtv_special(tcp, addr) \
printtv_bitness((tcp), (addr), BITNESS_CURRENT, 1)
-#ifdef __STDC__
-#ifdef __GNUC__
-extern void tprintf(const char *fmt, ...)
- __attribute__ ((format (printf, 1, 2)));
-#else
-extern void tprintf(const char *fmt, ...);
-#endif
-#else
-extern void tprintf();
-#endif
+extern void tprintf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+extern void tprints(const char *str);
#ifndef HAVE_STRERROR
-const char *strerror P((int));
+const char *strerror(int);
#endif
#ifndef HAVE_STRSIGNAL
-const char *strsignal P((int));
+const char *strsignal(int);
#endif
extern int current_personality;
extern const int personality_wordsize[];
struct sysent {
- int nargs;
+ unsigned nargs;
int sys_flags;
int (*sys_func)();
const char *sys_name;
long native_scno; /* Match against SYS_* constants. */
};
-extern const struct sysent *sysent;
-extern int nsyscalls;
-
-extern const char *const *errnoent;
-extern int nerrnos;
-
struct ioctlent {
const char *doth;
const char *symbol;
unsigned long code;
};
+extern const struct sysent *sysent;
+extern unsigned nsyscalls;
+extern const char *const *errnoent;
+extern unsigned nerrnos;
extern const struct ioctlent *ioctlent;
-extern int nioctlents;
-
+extern unsigned nioctlents;
extern const char *const *signalent;
-extern int nsignals;
-
-extern const struct ioctlent ioctlent0[];
-extern const int nioctlents0;
-extern const char *const signalent0[];
-extern const int nsignals0;
-
-#if SUPPORTED_PERSONALITIES >= 2
-extern const struct ioctlent ioctlent1[];
-extern const int nioctlents1;
-extern const char *const signalent1[];
-extern const int nsignals1;
-#endif /* SUPPORTED_PERSONALITIES >= 2 */
-
-#if SUPPORTED_PERSONALITIES >= 3
-extern const struct ioctlent ioctlent2[];
-extern const int nioctlents2;
-extern const char *const signalent2[];
-extern const int nsignals2;
-#endif /* SUPPORTED_PERSONALITIES >= 3 */
-
-#if defined(FREEBSD) || (defined(LINUX) \
- && defined(POWERPC) && !defined(__powerpc64__)) \
- || defined (LINUX_MIPSO32)
-/* ARRGH! off_t args are aligned on 64 bit boundaries! */
-#define ALIGN64(tcp,arg) \
-do { \
- if (arg % 2) \
- memmove (&tcp->u_arg[arg], &tcp->u_arg[arg + 1], \
- (tcp->u_nargs - arg - 1) * sizeof tcp->u_arg[0]); \
-} while (0)
-#else
-#define ALIGN64(tcp,arg) do { } while (0)
-#endif
+extern unsigned nsignals;
+
+#define SCNO_IN_RANGE(scno) ((unsigned long)(scno) < nsyscalls)
#if HAVE_LONG_LONG
#define LONG_LONG(_l,_h) \
((long long)((unsigned long long)(unsigned)(_h) | ((unsigned long long)(_l)<<32)))
#endif
+
+extern int printllval(struct tcb *, const char *, int);
#endif
#ifdef IA64
#endif
extern int not_failing_only;
+extern int show_fd_path;
+extern int tracing_paths;