aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2015-12-20 01:10:57 -0500
committerMike Frysinger <vapier@gentoo.org>2015-12-20 01:10:57 -0500
commita178ab35775d851e65df1408471681aa023b6dbc (patch)
tree2eb7171c3e7cceaf915275492f2b7b5bb036be3c
parentlibsandbox: avoid mixing stderr & output pipes (diff)
downloadsandbox-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.c34
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;