aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac25
-rw-r--r--headers.h13
-rw-r--r--libsandbox/trace.c13
-rw-r--r--libsandbox/trace/linux/arch.c4
-rw-r--r--libsandbox/trace/linux/bfin.c24
-rw-r--r--libsandbox/trace/linux/hppa.c34
-rw-r--r--libsandbox/trace/linux/i386.c4
-rw-r--r--libsandbox/trace/linux/x86_64.c6
-rw-r--r--localdecls.h8
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
diff --git a/headers.h b/headers.h
index f5d158d..7b9efb9 100644
--- a/headers.h
+++ b/headers.h
@@ -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, &regs);
+ ret = trace_get_regs(&regs);
if (before_syscall) {
_SB_DEBUG("%s:%i", se ? se->name : "IDK", nr);
if (!trace_check_syscall(se, &regs)) {
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