diff options
-rw-r--r-- | libsandbox/trace.c | 1 | ||||
-rw-r--r-- | libsandbox/trace/linux/arch.c | 2 | ||||
-rw-r--r-- | libsandbox/trace/linux/ia64.c | 81 |
3 files changed, 84 insertions, 0 deletions
diff --git a/libsandbox/trace.c b/libsandbox/trace.c index 5ccda2a..fb1fc32 100644 --- a/libsandbox/trace.c +++ b/libsandbox/trace.c @@ -9,6 +9,7 @@ #include "wrappers.h" #include "sb_nr.h" +static long do_peekdata(long offset); static long _do_ptrace(enum __ptrace_request request, const char *srequest, void *addr, void *data); #define do_ptrace(request, addr, data) _do_ptrace(request, #request, addr, data) #define _trace_possible(data) true diff --git a/libsandbox/trace/linux/arch.c b/libsandbox/trace/linux/arch.c index fbf5b79..4b3d615 100644 --- a/libsandbox/trace/linux/arch.c +++ b/libsandbox/trace/linux/arch.c @@ -17,6 +17,8 @@ # include "hppa.c" #elif defined(__i386__) # include "i386.c" +#elif defined(__ia64__) +# include "ia64.c" #elif defined(__powerpc__) # include "powerpc.c" #elif defined(__s390__) diff --git a/libsandbox/trace/linux/ia64.c b/libsandbox/trace/linux/ia64.c new file mode 100644 index 0000000..5029994 --- /dev/null +++ b/libsandbox/trace/linux/ia64.c @@ -0,0 +1,81 @@ +#include <asm/ptrace_offsets.h> +#include <asm/rse.h> + +/* We only care about two ptrace regs, so extract them ourselves rather than + * get the "full" set via GETREGS. We still need to extract the out regs by + * hand either way. + */ +#undef trace_regs +struct sb_ia64_trace_regs { + unsigned long r8, r10, r15; + unsigned long out[6]; +}; +#define trace_regs struct sb_ia64_trace_regs + +#define trace_reg_sysnum r15 + +static unsigned long trace_arg(void *vregs, int num) +{ + trace_regs *regs = vregs; + if (num < 7) + return regs->out[num - 1]; + else + return -1; +} + +static long do_peekuser(long offset) +{ + return do_ptrace(PTRACE_PEEKUSER, (void *)offset, NULL); +} + +static long do_pokeuser(long offset, long val) +{ + return do_ptrace(PTRACE_POKEUSER, (void *)offset, (void *)val); +} + +#undef trace_get_regs +static long trace_get_regs(void *vregs) +{ + trace_regs *regs = vregs; + size_t i; + unsigned long *out0, cfm, sof, sol; + long rbs_end; + + regs->r15 = do_peekuser(PT_R15); + + /* Here there be gremlins! */ + rbs_end = do_peekuser(PT_AR_BSP); + cfm = do_peekuser(PT_CFM); + sof = (cfm >> 0) & 0x7f; + sol = (cfm >> 7) & 0x7f; + out0 = ia64_rse_skip_regs((unsigned long *)rbs_end, -sof + sol); + for (i = 0; i < 7; ++i) + regs->out[i] = do_peekdata((uintptr_t)ia64_rse_skip_regs(out0, i)); + + return 0; +} + +#undef trace_set_regs +static long trace_set_regs(void *vregs) +{ + trace_regs *regs = vregs; + /* We only support rewriting of syscall/err # currently (not args). */ + do_pokeuser(PT_R8, regs->r8); + do_pokeuser(PT_R10, regs->r10); + do_pokeuser(PT_R15, regs->r15); + return 0; +} + +static long trace_raw_ret(void *vregs) +{ + trace_regs *regs = vregs; + return regs->r8; +} + +static void trace_set_ret(void *vregs, int err) +{ + trace_regs *regs = vregs; + regs->r8 = err; + regs->r10 = -1; + trace_set_regs(regs); +} |