diff options
author | 2015-12-20 01:10:57 -0500 | |
---|---|---|
committer | 2015-12-20 01:10:57 -0500 | |
commit | a178ab35775d851e65df1408471681aa023b6dbc (patch) | |
tree | 2eb7171c3e7cceaf915275492f2b7b5bb036be3c | |
parent | libsandbox: avoid mixing stderr & output pipes (diff) | |
download | sandbox-a178ab35775d851e65df1408471681aa023b6dbc.tar.gz sandbox-a178ab35775d851e65df1408471681aa023b6dbc.tar.bz2 sandbox-a178ab35775d851e65df1408471681aa023b6dbc.zip |
libsandbox: improve sparc trace code a bit more
This gets most of the tests passing, but syscall canceling still
does not work. Need to talk to upstream to figure it out.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
-rw-r--r-- | libsandbox/trace/linux/sparc.c | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/libsandbox/trace/linux/sparc.c b/libsandbox/trace/linux/sparc.c index f410b73..b59a036 100644 --- a/libsandbox/trace/linux/sparc.c +++ b/libsandbox/trace/linux/sparc.c @@ -1,20 +1,28 @@ #define SB_NO_TRACE_ARCH #if 0 /* XXX: broken sometimes #293632 */ -/* 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. +/* Since sparc's g0 register is hardcoded to 0 in the ISA, the kernel does not + * bother copying it out when using the regs ptrace. Instead it shifts things + * by one and stores [g1..g7] in [0..6] and [o0..o7] in [7..14] (leaving the + * last u_reg[15] unused). + * + * Oddly, the kernel defines are not adjusted to the values as they written in + * the register structure -- UREG_G0 is 0, UREG_G1 is 1, etc... So we have to + * define our own to get correct behavior. Also, the kernel uses UREG_I# when + * it's easier for us to think of it in terms of UREG_O# (register windows!). + * + * This should work for both 32 and 64 bit Linux userland. */ #define U_REG_G1 0 #define U_REG_O0 7 -static int trace_sysnum_regs(void *vregs) -{ - trace_regs *regs = vregs; - return regs->u_regs[U_REG_G1] ? : SB_SYS_EXECVE; -} - +/* Sparc systems have swapped the addr/data args. */ #undef trace_get_regs #define trace_get_regs(regs) do_ptrace(PTRACE_GETREGS, regs, NULL) +#undef trace_set_regs +#define trace_set_regs(regs) do_ptrace(PTRACE_SETREGS, regs, NULL) + +#define trace_reg_sysnum u_regs[U_REG_G1] static long trace_raw_ret(void *vregs) { @@ -22,6 +30,16 @@ static long trace_raw_ret(void *vregs) return regs->u_regs[U_REG_O0]; } +static void trace_set_ret(void *vregs, int err) +{ + trace_regs *regs = vregs; + /* The carry bit is used to flag errors. */ + regs->psr |= PSR_C; + /* Userland negates the value on sparc. */ + regs->u_regs[U_REG_O0] = err; + trace_set_regs(regs); +} + static unsigned long trace_arg(void *vregs, int num) { trace_regs *regs = vregs; |