#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-#ifdef _LARGEFILE64_SOURCE
-/* This is the macro everything checks before using foo64 names. */
-# ifndef _LFS64_LARGEFILE
-# define _LFS64_LARGEFILE 1
-# endif
-#endif
#ifdef MIPS
# include <sgidefs.h>
#define USE_SEIZE 1
/* To force NOMMU build, set to 1 */
#define NOMMU_SYSTEM 0
+/*
+ * Set to 1 to use speed-optimized vfprintf implementation.
+ * It results in strace using about 5% less CPU in user space
+ * (compared to glibc version).
+ * But strace spends a lot of time in kernel space,
+ * so overall it does not appear to be a significant win.
+ * Thus disabled by default.
+ */
+#define USE_CUSTOM_PRINTF 0
-#if (defined(SPARC) || defined(SPARC64) \
- || defined(I386) || defined(X32) || defined(X86_64) \
- || defined(ARM) || defined(AARCH64) \
- || defined(AVR32) \
- || defined(OR1K) \
- || defined(METAG) \
- || defined(TILE) \
- || defined(XTENSA) \
- ) && defined(__GLIBC__)
-# include <sys/ptrace.h>
-#else
-/* Work around awkward prototype in ptrace.h. */
+#ifdef NEED_PTRACE_PROTOTYPE_WORKAROUND
# define ptrace xptrace
# include <sys/ptrace.h>
# undef ptrace
-# ifdef POWERPC
-# define __KERNEL__
-# include <asm/ptrace.h>
-# undef __KERNEL__
-# endif
extern long ptrace(int, int, char *, long);
+#else
+# include <sys/ptrace.h>
+#endif
+
+#if defined(POWERPC)
+# include <asm/ptrace.h>
#endif
#if defined(TILE)
# include <asm/ptrace.h> /* struct pt_regs */
#endif
+#ifndef ERESTARTSYS
+# define ERESTARTSYS 512
+#endif
+#ifndef ERESTARTNOINTR
+# define ERESTARTNOINTR 513
+#endif
+#ifndef ERESTARTNOHAND
+# define ERESTARTNOHAND 514
+#endif
+#ifndef ERESTART_RESTARTBLOCK
+# define ERESTART_RESTARTBLOCK 516
+#endif
+
#if !HAVE_DECL_PTRACE_SETOPTIONS
# define PTRACE_SETOPTIONS 0x4200
#endif
# define PTRACE_EVENT_EXIT 6
#endif
-#if !defined(__GLIBC__)
+#if !HAVE_DECL_PTRACE_PEEKUSER
# define PTRACE_PEEKUSER PTRACE_PEEKUSR
+#endif
+#if !HAVE_DECL_PTRACE_POKEUSER
# define PTRACE_POKEUSER PTRACE_POKEUSR
#endif
-#if USE_SEIZE
-# undef PTRACE_SEIZE
-# define PTRACE_SEIZE 0x4206
-# undef PTRACE_INTERRUPT
-# define PTRACE_INTERRUPT 0x4207
-# undef PTRACE_LISTEN
-# define PTRACE_LISTEN 0x4208
-# undef PTRACE_EVENT_STOP
-# define PTRACE_EVENT_STOP 128
-#endif
+#undef PTRACE_SEIZE
+#define PTRACE_SEIZE 0x4206
+#undef PTRACE_INTERRUPT
+#define PTRACE_INTERRUPT 0x4207
+#undef PTRACE_LISTEN
+#define PTRACE_LISTEN 0x4208
+#undef PTRACE_EVENT_STOP
+#define PTRACE_EVENT_STOP 128
#ifdef ALPHA
# define REG_R0 0
# define DEFAULT_PERSONALITY 0
#endif
#ifndef PERSONALITY0_WORDSIZE
-# define PERSONALITY0_WORDSIZE (int)(sizeof(long))
+# define PERSONALITY0_WORDSIZE SIZEOF_LONG
#endif
-#if defined(I386)
-extern struct user_regs_struct i386_regs;
+#if defined(I386) || defined(X86_64)
+extern uint32_t *const i386_esp_ptr;
#elif defined(IA64)
-extern long ia32;
+extern bool ia64_ia32mode;
#elif defined(SPARC) || defined(SPARC64)
extern struct pt_regs sparc_regs;
#elif defined(ARM)
extern struct pt_regs arm_regs;
#elif defined(TILE)
extern struct pt_regs tile_regs;
+#elif defined(POWERPC)
+extern struct pt_regs ppc_regs;
#endif
typedef struct sysent {
/* Trace Control Block */
struct tcb {
int flags; /* See below for TCB_ values */
- int pid; /* Process Id of this entry */
+ int pid; /* If 0, this tcb is free */
int qual_flg; /* qual_flags[scno] or DEFAULT_QUAL_FLAGS + RAW */
int u_error; /* Error code */
long scno; /* System call number */
#endif
long u_rval; /* Return value */
#if SUPPORTED_PERSONALITIES > 1
- int currpers; /* Personality at the time of scno update */
+ unsigned int currpers; /* Personality at the time of scno update */
#endif
int curcol; /* Output column for this process */
FILE *outf; /* Output file for this process */
struct timeval etime; /* Syscall entry time */
/* Support for tracing forked processes: */
long inst[2]; /* Saved clone args (badly named) */
+
+#ifdef USE_LIBUNWIND
+ struct UPT_info* libunwind_ui;
+ struct mmap_cache_t* mmap_cache;
+ unsigned int mmap_cache_size;
+ unsigned int mmap_cache_generation;
+ struct queue_t* queue;
+#endif
};
/* TCB flags */
-#define TCB_INUSE 00001 /* This table entry is in use */
/* We have attached to this process, but did not see it stopping yet */
-#define TCB_STARTUP 00002
-#define TCB_IGNORE_ONE_SIGSTOP 00004 /* Next SIGSTOP is to be ignored */
+#define TCB_STARTUP 0x01
+#define TCB_IGNORE_ONE_SIGSTOP 0x02 /* Next SIGSTOP is to be ignored */
/*
* Are we in system call entry or in syscall exit?
*
*
* Use entering(tcp) / exiting(tcp) to check this bit to make code more readable.
*/
-#define TCB_INSYSCALL 00010
-#define TCB_ATTACHED 00020 /* It is attached already */
-/* Are we PROG from "strace PROG [ARGS]" invocation? */
-#define TCB_STRACE_CHILD 0040
-#define TCB_BPTSET 00100 /* "Breakpoint" set after fork(2) */
-#define TCB_REPRINT 00200 /* We should reprint this syscall on exit */
-#define TCB_FILTERED 00400 /* This system call has been filtered out */
-/* x86 does not need TCB_WAITEXECVE.
+#define TCB_INSYSCALL 0x04
+#define TCB_ATTACHED 0x08 /* We attached to it already */
+#define TCB_BPTSET 0x10 /* "Breakpoint" set after fork(2) */
+#define TCB_REPRINT 0x20 /* We should reprint this syscall on exit */
+#define TCB_FILTERED 0x40 /* This system call has been filtered out */
+/*
+ * x86 does not need TCB_WAITEXECVE.
* It can detect post-execve SIGTRAP by looking at eax/rax.
* See "not a syscall entry (eax = %ld)\n" message.
*
/* 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 01000
+# define TCB_WAITEXECVE 0x80
#endif
/* qualifier flags */
#define filtered(tcp) ((tcp)->flags & TCB_FILTERED)
struct xlat {
- int val;
+ unsigned int val;
const char *str;
};
+#define XLAT(x) { x, #x }
+#define XLAT_END { 0, NULL }
extern const struct xlat open_mode_flags[];
extern const struct xlat addrfams[];
# endif
# define RVAL_LUDECIMAL 007 /* long unsigned decimal format */
#endif
-#define RVAL_MASK 007 /* mask for these values */
+#define RVAL_FD 010 /* file descriptor */
+#define RVAL_MASK 017 /* mask for these values */
-#define RVAL_STR 010 /* Print `auxstr' field after return val */
-#define RVAL_NONE 020 /* Print nothing */
+#define RVAL_STR 020 /* Print `auxstr' field after return val */
+#define RVAL_NONE 040 /* Print nothing */
#define TRACE_FILE 001 /* Trace file-related syscalls. */
#define TRACE_IPC 002 /* Trace IPC-related syscalls. */
#define TRACE_DESC 040 /* Trace file descriptor-related syscalls. */
#define TRACE_MEMORY 0100 /* Trace memory mapping-related syscalls. */
#define SYSCALL_NEVER_FAILS 0200 /* Syscall is always successful. */
+#define STACKTRACE_INVALIDATE_CACHE 0400 /* Trigger proc/maps cache updating */
+#define STACKTRACE_CAPTURE_ON_ENTER 01000 /* Capture stacktrace on "entering" stage */
typedef enum {
CFLAG_NONE = 0,
extern cflag_t cflag;
extern bool debug_flag;
extern bool Tflag;
+extern bool iflag;
+extern bool count_wallclock;
extern unsigned int qflag;
extern bool not_failing_only;
-extern bool show_fd_path;
+extern unsigned int show_fd_path;
+extern bool hide_log_until_execve;
/* are we filtering traces based on paths? */
extern const char **paths_selected;
#define tracing_paths (paths_selected != NULL)
extern bool need_fork_exec_workarounds;
extern unsigned xflag;
extern unsigned followfork;
+#ifdef USE_LIBUNWIND
+/* if this is true do the stack trace for every system call */
+extern bool stack_trace_enabled;
+#endif
extern unsigned ptrace_setoptions;
extern unsigned max_strlen;
extern unsigned os_release;
void perror_msg_and_die(const char *fmt, ...) __attribute__ ((noreturn, format(printf, 1, 2)));
void die_out_of_memory(void) __attribute__ ((noreturn));
-#ifdef USE_CUSTOM_PRINTF
+#if USE_CUSTOM_PRINTF
/*
- * Speed-optimized vfprintf implementation.
* See comment in vsprintf.c for allowed formats.
* Short version: %h[h]u, %zu, %tu are not allowed, use %[l[l]]u.
- *
- * It results in strace using about 5% less CPU in user space
- * (compared to glibc version).
- * But strace spends a lot of time in kernel space,
- * so overall it does not appear to be a significant win.
- * Thus disabled by default.
*/
int strace_vfprintf(FILE *fp, const char *fmt, va_list args);
#else
extern void set_sortby(const char *);
extern void set_overhead(int);
extern void qualify(const char *);
+extern void print_pc(struct tcb *);
extern int trace_syscall(struct tcb *);
-extern void count_syscall(struct tcb *, struct timeval *);
+extern void count_syscall(struct tcb *, const struct timeval *);
extern void call_summary(FILE *);
#if defined(AVR32) \
|| defined(SPARC) || defined(SPARC64) \
|| defined(TILE) \
|| defined(OR1K) \
- || defined(METAG)
+ || defined(METAG) \
+ || defined(ARC) \
+ || defined(POWERPC)
extern long get_regs_error;
# define clear_regs() (get_regs_error = -1)
extern void get_regs(pid_t pid);
#define umove(pid, addr, objp) \
umoven((pid), (addr), sizeof(*(objp)), (char *) (objp))
extern int umovestr(struct tcb *, long, int, char *);
-extern int upeek(struct tcb *, long, long *);
+extern int upeek(int pid, long, long *);
#if defined(SPARC) || defined(SPARC64) || defined(IA64) || defined(SH)
extern long getrval2(struct tcb *);
#endif
extern int setbpt(struct tcb *);
extern int clearbpt(struct tcb *);
-extern const char *signame(int);
-extern int is_restart_error(struct tcb *);
+extern const char *signame(const int);
extern void pathtrace_select(const char *);
extern int pathtrace_match(struct tcb *);
extern int getfdpath(struct tcb *, int, char *, unsigned);
-extern const char *xlookup(const struct xlat *, int);
+extern const char *xlookup(const struct xlat *, const unsigned int);
+extern const char *xlat_search(const struct xlat *, const size_t, const unsigned int);
extern int string_to_uint(const char *str);
extern int string_quote(const char *, char *, long, int);
+extern int next_set_bit(const void *bit_array, unsigned cur_bit, unsigned size_bits);
/* a refers to the lower numbered u_arg,
* b refers to the higher numbered u_arg
#endif
extern int printllval(struct tcb *, const char *, int);
-extern void printxval(const struct xlat *, int, const char *);
+extern void printxval(const struct xlat *, const unsigned int, const char *);
extern int printargs(struct tcb *);
extern int printargs_lu(struct tcb *);
extern int printargs_ld(struct tcb *);
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 printpathn(struct tcb *, long, unsigned int);
#define TIMESPEC_TEXT_BUFSIZE (sizeof(long)*3 * 2 + sizeof("{%u, %u}"))
#define TIMEVAL_TEXT_BUFSIZE TIMESPEC_TEXT_BUFSIZE
extern void printtv_bitness(struct tcb *, long, enum bitness_t, int);
extern void printsiginfo_at(struct tcb *tcp, long addr);
#endif
extern void printfd(struct tcb *, int);
+extern bool print_sockaddr_by_inode(const unsigned long);
+extern void print_dirfd(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);
extern void printrusage32(struct tcb *, long);
#endif
extern void printuid(const char *, unsigned long);
-extern void printcall(struct tcb *);
-extern void print_sigset(struct tcb *, long, int);
+extern void print_sigset_addr_len(struct tcb *, long, long);
extern void printsignal(int);
extern void tprint_iov(struct tcb *, unsigned long, unsigned long, int decode_iov);
extern void tprint_iov_upto(struct tcb *, unsigned long, unsigned long, int decode_iov, unsigned long);
extern const char *sprint_open_modes(mode_t);
extern void print_loff_t(struct tcb *, long);
-extern const struct_ioctlent *ioctl_lookup(long);
+extern const struct_ioctlent *ioctl_lookup(unsigned 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 mtd_ioctl(struct tcb *, long, long);
extern int ubi_ioctl(struct tcb *, long, long);
extern int loop_ioctl(struct tcb *, long, long);
-
-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);
+extern int ptp_ioctl(struct tcb *, long, long);
+
+extern int tv_nz(const struct timeval *);
+extern int tv_cmp(const struct timeval *, const struct timeval *);
+extern double tv_float(const struct timeval *);
+extern void tv_add(struct timeval *, const struct timeval *, const struct timeval *);
+extern void tv_sub(struct timeval *, const struct timeval *, const struct timeval *);
+extern void tv_mul(struct timeval *, const struct timeval *, int);
+extern void tv_div(struct timeval *, const struct timeval *, int);
+
+#ifdef USE_LIBUNWIND
+extern void unwind_init(void);
+extern void unwind_tcb_init(struct tcb *tcp);
+extern void unwind_tcb_fin(struct tcb *tcp);
+extern void unwind_cache_invalidate(struct tcb* tcp);
+extern void unwind_print_stacktrace(struct tcb* tcp);
+extern void unwind_capture_stacktrace(struct tcb* tcp);
+#endif
/* Strace log generation machinery.
*