diff options
-rw-r--r-- | configure.ac | 25 | ||||
-rw-r--r-- | headers.h | 13 | ||||
-rw-r--r-- | libsandbox/trace.c | 13 | ||||
-rw-r--r-- | libsandbox/trace/linux/arch.c | 4 | ||||
-rw-r--r-- | libsandbox/trace/linux/bfin.c | 24 | ||||
-rw-r--r-- | libsandbox/trace/linux/hppa.c | 34 | ||||
-rw-r--r-- | libsandbox/trace/linux/i386.c | 4 | ||||
-rw-r--r-- | libsandbox/trace/linux/x86_64.c | 6 | ||||
-rw-r--r-- | localdecls.h | 8 |
9 files changed, 122 insertions, 9 deletions
diff --git a/configure.ac b/configure.ac index 24e055c..a80f587 100644 --- a/configure.ac +++ b/configure.ac @@ -97,6 +97,8 @@ AC_CHECK_HEADERS_ONCE([ \ sys/types.h \ sys/user.h \ sys/wait.h \ + asm/ptrace.h \ + linux/ptrace.h \ ]) dnl Checks for typedefs, structures, and compiler characteristics. @@ -105,9 +107,30 @@ AC_C_CONST AC_TYPE_UID_T AC_TYPE_MODE_T AC_TYPE_SIZE_T +AC_CHECK_DECLS_ONCE([environ]) AC_CHECK_TYPES([ptrdiff_t]) AC_CHECK_TYPES([sighandler_t, sig_t, __sighandler_t],,,[#include <signal.h>]) -AC_CHECK_DECLS_ONCE([environ]) + +AC_CHECK_TYPES([struct user_regs_struct, struct pt_regs],,,[$ac_includes_default +#ifdef HAVE_SYS_PTRACE_H +# include <sys/ptrace.h> +#endif +#ifdef HAVE_SYS_USER_H +# include <sys/user.h> +#endif +#ifdef __ia64__ /* what a pos */ +# define ia64_fpreg FU_ia64_fpreg +# define pt_all_user_regs FU_pt_all_user_regs +#endif +#ifdef HAVE_LINUX_PTRACE_H +# include <linux/ptrace.h> +#endif +#ifdef HAVE_ASM_PTRACE_H +# include <asm/ptrace.h> +#endif +#undef FU_ia64_fpreg +#undef FU_pt_all_user_regs +]) dnl Checks for library functions. AC_FUNC_CHOWN @@ -118,6 +118,19 @@ # include <sys/wait.h> #endif +#ifdef __ia64__ /* what a pos */ +# define ia64_fpreg FU_ia64_fpreg +# define pt_all_user_regs FU_pt_all_user_regs +#endif +#ifdef HAVE_ASM_PTRACE_H +# include <asm/ptrace.h> +#endif +#ifdef HAVE_LINUX_PTRACE_H +# include <linux/ptrace.h> +#endif +#undef FU_ia64_fpreg +#undef FU_pt_all_user_regs + #include "localdecls.h" #endif diff --git a/libsandbox/trace.c b/libsandbox/trace.c index 1fdeee6..6805a24 100644 --- a/libsandbox/trace.c +++ b/libsandbox/trace.c @@ -316,9 +316,16 @@ static bool trace_check_syscall(const struct syscall_entry *se, void *regs) return ret; } +/* Some arches (like hppa) don't implement PTRACE_GETREGS ... + * what a bunch of asshats. + */ +#ifndef trace_get_regs +# define trace_get_regs(regs) do_ptrace(PTRACE_GETREGS, NULL, regs); +#endif + static void trace_loop(void) { - struct user_regs_struct regs; + trace_regs regs; bool before_syscall; long ret; int nr, exec_state; @@ -337,7 +344,7 @@ static void trace_loop(void) se = lookup_syscall_in_tbl(tbl_at_fork, nr); if (!before_syscall || !se || se->sys != SB_NR_EXECVE) { if (before_syscall) - _SB_DEBUG("%s:%i", se ? se->name : "IDK", nr); + _SB_DEBUG(">%s:%i", se ? se->name : "IDK", nr); else __SB_DEBUG("(...) = ...\n"); goto loop_again; @@ -346,7 +353,7 @@ static void trace_loop(void) } se = lookup_syscall(nr); - ret = do_ptrace(PTRACE_GETREGS, NULL, ®s); + ret = trace_get_regs(®s); if (before_syscall) { _SB_DEBUG("%s:%i", se ? se->name : "IDK", nr); if (!trace_check_syscall(se, ®s)) { diff --git a/libsandbox/trace/linux/arch.c b/libsandbox/trace/linux/arch.c index 5897b2f..f9d7762 100644 --- a/libsandbox/trace/linux/arch.c +++ b/libsandbox/trace/linux/arch.c @@ -3,6 +3,10 @@ /* Linux uses ptrace() */ #if !defined(HAVE_PTRACE) || !defined(HAVE_SYS_PTRACE_H) || !defined(HAVE_SYS_USER_H) # define SB_NO_TRACE_ARCH +#elif defined(__bfin__) +# include "bfin.c" +#elif defined(__hppa__) +# include "hppa.c" #elif defined(__i386__) # include "i386.c" #elif defined(__x86_64__) diff --git a/libsandbox/trace/linux/bfin.c b/libsandbox/trace/linux/bfin.c new file mode 100644 index 0000000..4188034 --- /dev/null +++ b/libsandbox/trace/linux/bfin.c @@ -0,0 +1,24 @@ +static int trace_sysnum(void) +{ + return do_peekuser(PT_ORIG_P0); +} + +static long trace_raw_ret(void *vregs) +{ + trace_regs *regs = vregs; + return regs->r0; +} + +static unsigned long trace_arg(void *vregs, int num) +{ + trace_regs *regs = vregs; + switch (num) { + case 1: return regs->r0; + case 2: return regs->r1; + case 3: return regs->r2; + case 4: return regs->r3; + case 5: return regs->r4; + case 6: return regs->r5; + default: return -1; + } +} diff --git a/libsandbox/trace/linux/hppa.c b/libsandbox/trace/linux/hppa.c new file mode 100644 index 0000000..d98310f --- /dev/null +++ b/libsandbox/trace/linux/hppa.c @@ -0,0 +1,34 @@ +static int trace_sysnum(void) +{ + return do_peekuser(20 * 4); /* PT_GR20 */ +} + +static long trace_raw_ret(void *vregs) +{ + trace_regs *regs = vregs; + return regs->gr[28]; +} + +static unsigned long trace_arg(void *vregs, int num) +{ + trace_regs *regs = vregs; + switch (num) { + case 1: return regs->gr[26]; + case 2: return regs->gr[25]; + case 3: return regs->gr[24]; + case 4: return regs->gr[23]; + case 5: return regs->gr[22]; + case 6: return regs->gr[21]; + default: return -1; + } +} + +static long trace_get_regs(void *vregs) +{ + trace_regs *regs = vregs; + size_t i; + for (i = 21; i < 29; ++i) + regs->gr[i] = do_peekuser(i * 4); + return 0; +} +#define trace_get_regs trace_get_regs diff --git a/libsandbox/trace/linux/i386.c b/libsandbox/trace/linux/i386.c index 83cc094..7508e25 100644 --- a/libsandbox/trace/linux/i386.c +++ b/libsandbox/trace/linux/i386.c @@ -5,13 +5,13 @@ static int trace_sysnum(void) static long trace_raw_ret(void *vregs) { - struct user_regs_struct *regs = vregs; + trace_regs *regs = vregs; return regs->eax; } static unsigned long trace_arg(void *vregs, int num) { - struct user_regs_struct *regs = vregs; + trace_regs *regs = vregs; switch (num) { case 1: return regs->ebx; case 2: return regs->ecx; diff --git a/libsandbox/trace/linux/x86_64.c b/libsandbox/trace/linux/x86_64.c index 96e732e..b864801 100644 --- a/libsandbox/trace/linux/x86_64.c +++ b/libsandbox/trace/linux/x86_64.c @@ -43,13 +43,13 @@ static int trace_sysnum(void) static long trace_raw_ret(void *vregs) { - struct user_regs_struct *regs = vregs; + trace_regs *regs = vregs; return pers_is_32() ? (int)regs->rax : regs->rax; } static unsigned long trace_arg(void *vregs, int num) { - struct user_regs_struct *regs = vregs; + trace_regs *regs = vregs; if (pers_is_32()) switch (num) { case 1: return regs->rbx; @@ -75,7 +75,7 @@ static unsigned long trace_arg(void *vregs, int num) #ifdef DEBUG static void trace_dump_regs(void *vregs) { - struct user_regs_struct *regs = vregs; + trace_regs *regs = vregs; sb_printf("{ "); #define D(r) sb_printf(#r":%lu ", regs->r) D(rax); diff --git a/localdecls.h b/localdecls.h index 595a5ac..83c01d6 100644 --- a/localdecls.h +++ b/localdecls.h @@ -63,6 +63,14 @@ typedef __sighandler_t sighandler_t; # endif #endif +#if defined(HAVE_STRUCT_PT_REGS) +typedef struct pt_regs trace_regs; +#elif defined(HAVE_STRUCT_USER_REGS_STRUCT) +typedef struct user_regs_struct trace_regs; +#else +# error "unable to find struct for tracing regs" +#endif + #ifndef ARRAY_SIZE #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) #endif |