return ret;
}
-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);
-}
-
static long do_peekdata(long offset)
{
return do_ptrace(PTRACE_PEEKDATA, (void *)offset, NULL);
++tbl;
return NULL;
}
-static const struct syscall_entry *lookup_syscall(int nr)
-{
- return lookup_syscall_in_tbl(trace_check_personality(), nr);
-}
struct syscall_state {
void *regs;
return ret;
}
-/* Some arches (like hppa) don't implement PTRACE_GETREGS, while others (like
- * sparc) swap the meaning of "addr" and "data. What a bunch of asshats.
- */
-#ifndef trace_get_regs
-# define trace_get_regs(regs) do_ptrace(PTRACE_GETREGS, NULL, regs)
-#endif
-#ifndef trace_set_regs
-# define trace_set_regs(regs) do_ptrace(PTRACE_SETREGS, NULL, regs)
-#endif
-/* Some arches (like sparc) don't implement PTRACE_PEEK* ...
- * more asshats !
- */
-#ifndef trace_sysnum_regs
-# define trace_sysnum_regs(regs) trace_sysnum()
-#endif
-
static void trace_loop(void)
{
trace_regs regs;
bool before_syscall, fake_syscall_ret;
long ret;
int nr, exec_state;
- const struct syscall_entry *se, *tbl_at_fork;
+ const struct syscall_entry *se, *tbl_at_fork, *tbl_after_fork;
exec_state = 0;
before_syscall = true;
fake_syscall_ret = false;
- tbl_at_fork = NULL;
+ tbl_at_fork = tbl_after_fork = NULL;
do {
ret = do_ptrace(PTRACE_SYSCALL, NULL, NULL);
waitpid(trace_pid, NULL, 0);
- nr = trace_sysnum_regs(®s);
+ ret = trace_get_regs(®s);
+ nr = trace_get_sysnum(®s);
if (!exec_state) {
if (!tbl_at_fork)
- tbl_at_fork = trace_check_personality();
+ tbl_at_fork = trace_check_personality(®s);
se = lookup_syscall_in_tbl(tbl_at_fork, nr);
if (!before_syscall || !se || se->sys != SB_NR_EXECVE) {
if (before_syscall)
goto loop_again;
}
- se = lookup_syscall(nr);
+ if (!tbl_after_fork)
+ tbl_after_fork = trace_check_personality(®s);
+ se = lookup_syscall_in_tbl(tbl_after_fork, nr);
ret = trace_get_regs(®s);
if (before_syscall) {
_sb_debug("%s:%i", se ? se->name : "IDK", nr);
const char *name;
};
-static int trace_sysnum(void);
-static int trace_sysnum_regs(void *vregs);
+static int trace_get_sysnum(void *vregs);
static long trace_raw_ret(void *vregs);
static unsigned long trace_arg(void *vregs, int num);
#undef S
{ SB_NR_UNDEF, SB_NR_UNDEF, NULL },
};
-# define trace_check_personality() syscall_table
+# define trace_check_personality(regs) syscall_table
#endif
# warning "trace: sorry, no support for your architecture"
# define SB_NO_TRACE
#else
-# ifdef trace_sysnum_puser
-static int trace_sysnum(void)
+# ifdef trace_reg_sysnum
+static int trace_get_sysnum(void *vregs)
{
- return do_peekuser(trace_sysnum_puser);
+ trace_regs *regs = vregs;
+ return regs->trace_reg_sysnum;
}
-
static void trace_set_sysnum(void *vregs, long nr)
{
- do_pokeuser(trace_sysnum_puser, nr);
+ trace_regs *regs = vregs;
+ regs->trace_reg_sysnum = nr;
+ trace_set_regs(regs);
}
+# endif
+# ifdef trace_reg_ret
+static long trace_raw_ret(void *vregs)
+{
+ trace_regs *regs = vregs;
+ return regs->trace_reg_ret;
+}
+static void trace_set_ret(void *vregs, int err)
+{
+ trace_regs *regs = vregs;
+ regs->trace_reg_ret = -err;
+ trace_set_regs(regs);
+}
# endif
+
#endif
-#define trace_sysnum_puser PT_ORIG_P0
-
-static long trace_raw_ret(void *vregs)
-{
- trace_regs *regs = vregs;
- return regs->r0;
-}
-
-static void trace_set_ret(void *vregs, int err)
-{
- do_pokeuser(PT_R0, -err);
-}
+#define trace_reg_sysnum orig_p0
+#define trace_reg_ret r0
static unsigned long trace_arg(void *vregs, int num)
{
-static long do_peekuser(long offset);
-static long do_pokeuser(long offset, long val);
+/*
+ * Some arches (like hppa) don't implement PTRACE_GETREGS, while others (like
+ * sparc) swap the meaning of "addr" and "data. What a bunch of asshats.
+ */
+#define trace_get_regs(regs) do_ptrace(PTRACE_GETREGS, NULL, regs)
+#define trace_set_regs(regs) do_ptrace(PTRACE_SETREGS, NULL, regs)
static int trace_errno(long err)
{
-#define trace_sysnum_puser (20 * 4) /* PT_GR20 */
-
-static long trace_raw_ret(void *vregs)
-{
- trace_regs *regs = vregs;
- return regs->gr[28];
-}
-
-static void trace_set_ret(void *vregs, int err)
-{
- do_pokeuser(28 * 4 /* PT_GR28 */, -err);
-}
+#define trace_reg_sysnum (20 * 4) /* PT_GR20 */
+#define trace_reg_ret (28 * 4) /* PT_GR28 */
static unsigned long trace_arg(void *vregs, int num)
{
}
}
+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;
- for (i = 21; i < 29; ++i)
+ for (i = 20; i < 29; ++i)
regs->gr[i] = do_peekuser(i * 4);
return 0;
}
-#define trace_get_regs trace_get_regs
+
+#undef trace_set_regs
+static long trace_set_regs(void *vregs)
+{
+ trace_regs *regs = vregs;
+ size_t i;
+ for (i = 20; i < 29; ++i)
+ do_pokeuser(i * 4, regs->gr[i]);
+ return 0;
+}
-#define trace_sysnum_puser (4 * ORIG_EAX)
-
-static long trace_raw_ret(void *vregs)
-{
- trace_regs *regs = vregs;
- return regs->eax;
-}
-
-static void trace_set_ret(void *vregs, int err)
-{
- do_pokeuser(EAX, -err);
-}
+#define trace_reg_sysnum orig_eax
+#define trace_reg_ret eax
static unsigned long trace_arg(void *vregs, int num)
{
static int trace_sysnum_regs(void *vregs)
{
trace_regs *regs = vregs;
- do_ptrace(PTRACE_GETREGS, regs, NULL);
return regs->u_regs[U_REG_G1] ? : SB_SYS_EXECVE;
}
-#define trace_sysnum_regs(regs) trace_sysnum_regs(regs)
-#define trace_get_regs(regs) (0)
+
+#undef trace_get_regs
+#define trace_get_regs(regs) do_ptrace(PTRACE_GETREGS, regs, NULL)
static long trace_raw_ret(void *vregs)
{
{ SB_NR_UNDEF, SB_NR_UNDEF, NULL },
};
-static bool pers_is_32(void)
+static bool pers_is_32(trace_regs *regs)
{
- switch (do_peekuser(8 * CS)) {
+ switch (regs->cs) {
case 0x23: return true;
case 0x33: return false;
default: sb_ebort("unknown x86_64 personality");
}
}
-static const struct syscall_entry *trace_check_personality(void)
+static const struct syscall_entry *trace_check_personality(void *vregs)
{
- return pers_is_32() ? syscall_table_32 : syscall_table_64;
+ trace_regs *regs = vregs;
+ return pers_is_32(regs) ? syscall_table_32 : syscall_table_64;
}
#else
-static bool pers_is_32(void)
+static bool pers_is_32(trace_regs *regs)
{
return false;
}
#endif
-static int trace_sysnum(void)
-{
- return do_peekuser(8 * ORIG_RAX);
-}
+#define trace_reg_sysnum orig_rax
static long trace_raw_ret(void *vregs)
{
trace_regs *regs = vregs;
- return pers_is_32() ? (int)regs->rax : regs->rax;
-}
-
-static void trace_set_sysnum(void *vregs, long nr)
-{
- do_pokeuser(8 * ORIG_RAX, nr);
+ return pers_is_32(regs) ? (int)regs->rax : regs->rax;
}
static void trace_set_ret(void *vregs, int err)
{
- do_pokeuser(8 * RAX, -err);
+ trace_regs *regs = vregs;
+ regs->rax = -err;
+ trace_set_regs(regs);
}
static unsigned long trace_arg(void *vregs, int num)
{
trace_regs *regs = vregs;
- if (pers_is_32())
+ if (pers_is_32(regs))
switch (num) {
case 1: return regs->rbx;
case 2: return regs->rcx;