strace: generic interface to user registers
This commit is contained in:
parent
aa8d79c81a
commit
453486bc52
75
apps/dbg.c
75
apps/dbg.c
@ -27,6 +27,7 @@
|
|||||||
#include <toaru/rline.h>
|
#include <toaru/rline.h>
|
||||||
#include <toaru/hashmap.h>
|
#include <toaru/hashmap.h>
|
||||||
#include <kernel/elf.h>
|
#include <kernel/elf.h>
|
||||||
|
#include <sys/uregs.h>
|
||||||
|
|
||||||
static char * last_command = NULL;
|
static char * last_command = NULL;
|
||||||
static char * binary_path = NULL;
|
static char * binary_path = NULL;
|
||||||
@ -34,60 +35,10 @@ static FILE * binary_obj = NULL;
|
|||||||
static pid_t binary_pid = 0;
|
static pid_t binary_pid = 0;
|
||||||
static int binary_is_child = 0;
|
static int binary_is_child = 0;
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
static void dump_regs(struct URegs * r) {
|
||||||
#include <kernel/arch/x86_64/regs.h>
|
fprintf(stdout, UREGS_FMT, UREGS_ARGS(r));
|
||||||
static void dump_regs(struct regs * r) {
|
|
||||||
fprintf(stdout,
|
|
||||||
" $rip=0x%016lx\n"
|
|
||||||
" $rsi=0x%016lx,$rdi=0x%016lx,$rbp=0x%016lx,$rsp=0x%016lx\n"
|
|
||||||
" $rax=0x%016lx,$rbx=0x%016lx,$rcx=0x%016lx,$rdx=0x%016lx\n"
|
|
||||||
" $r8= 0x%016lx,$r9= 0x%016lx,$r10=0x%016lx,$r11=0x%016lx\n"
|
|
||||||
" $r12=0x%016lx,$r13=0x%016lx,$r14=0x%016lx,$r15=0x%016lx\n"
|
|
||||||
" cs=0x%016lx ss=0x%016lx rflags=0x%016lx int=0x%02lx err=0x%02lx\n",
|
|
||||||
r->rip,
|
|
||||||
r->rsi, r->rdi, r->rbp, r->rsp,
|
|
||||||
r->rax, r->rbx, r->rcx, r->rdx,
|
|
||||||
r->r8, r->r9, r->r10, r->r11,
|
|
||||||
r->r12, r->r13, r->r14, r->r15,
|
|
||||||
r->cs, r->ss, r->rflags, r->int_no, r->err_code
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
#define regs_ip(regs) ((regs)->rip)
|
|
||||||
#define regs_bp(regs) ((regs)->rbp)
|
|
||||||
#elif defined(__aarch64__)
|
|
||||||
#define regs _regs
|
|
||||||
#include <kernel/arch/aarch64/regs.h>
|
|
||||||
#undef regs
|
|
||||||
struct regs {
|
|
||||||
struct _regs gp;
|
|
||||||
uint64_t elr;
|
|
||||||
};
|
|
||||||
static void dump_regs(struct regs *r) {
|
|
||||||
#define reg(a,b) printf(" $x%02d=0x%016lx $x%02d=0x%016lx\n",a,r->gp.x ## a, b, r->gp.x ## b)
|
|
||||||
reg(0,1);
|
|
||||||
reg(2,3);
|
|
||||||
reg(4,5);
|
|
||||||
reg(6,7);
|
|
||||||
reg(8,9);
|
|
||||||
reg(10,11);
|
|
||||||
reg(12,13);
|
|
||||||
reg(14,15);
|
|
||||||
reg(16,17);
|
|
||||||
reg(18,19);
|
|
||||||
reg(20,21);
|
|
||||||
reg(22,23);
|
|
||||||
reg(24,25);
|
|
||||||
reg(26,27);
|
|
||||||
reg(28,29);
|
|
||||||
printf(" $x30=0x%016lx sp=0x%016lx\n", r->gp.x30, r->gp.user_sp);
|
|
||||||
printf(" elr=0x%016lx\n", r->elr);
|
|
||||||
#undef reg
|
|
||||||
#define regs_ip(regs) ((regs)->elr)
|
|
||||||
#define regs_bp(regs) ((regs)->gp.x29)
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
# error "Unsupported arch"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define M(e) [e] = #e
|
#define M(e) [e] = #e
|
||||||
const char * signal_names[256] = {
|
const char * signal_names[256] = {
|
||||||
@ -397,11 +348,11 @@ static void show_libs(pid_t pid) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void attempt_backtrace(pid_t pid, struct regs * regs) {
|
static void attempt_backtrace(pid_t pid, struct URegs * regs) {
|
||||||
|
|
||||||
/* We already printed the top, now let's try to dig down */
|
/* We already printed the top, now let's try to dig down */
|
||||||
uintptr_t ip = regs_ip(regs);
|
uintptr_t ip = uregs_ip(regs);
|
||||||
uintptr_t bp = regs_bp(regs);
|
uintptr_t bp = uregs_bp(regs);
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
int max_depth = 20;
|
int max_depth = 20;
|
||||||
|
|
||||||
@ -450,18 +401,18 @@ static int signal_from_string(const char * str) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_commandline(pid_t pid, int status, struct regs * regs) {
|
static void show_commandline(pid_t pid, int status, struct URegs * regs) {
|
||||||
|
|
||||||
fprintf(stderr, "[Process %d, ip=%#zx]\n",
|
fprintf(stderr, "[Process %d, ip=%#zx]\n",
|
||||||
pid, regs_ip(regs));
|
pid, uregs_ip(regs));
|
||||||
|
|
||||||
/* Try to figure out what symbol that is */
|
/* Try to figure out what symbol that is */
|
||||||
char * name = NULL;
|
char * name = NULL;
|
||||||
char * objname = NULL;
|
char * objname = NULL;
|
||||||
uintptr_t addr = 0;
|
uintptr_t addr = 0;
|
||||||
if (find_symbol(pid, regs_ip(regs), &name, &addr, &objname)) {
|
if (find_symbol(pid, uregs_ip(regs), &name, &addr, &objname)) {
|
||||||
fprintf(stderr, " %s+%zx in %s\n",
|
fprintf(stderr, " %s+%zx in %s\n",
|
||||||
name, regs_ip(regs) - addr, objname);
|
name, uregs_ip(regs) - addr, objname);
|
||||||
free(name);
|
free(name);
|
||||||
free(objname);
|
free(objname);
|
||||||
}
|
}
|
||||||
@ -767,7 +718,7 @@ int main(int argc, char * argv[]) {
|
|||||||
int event = (status >> 16) & 0xFF;
|
int event = (status >> 16) & 0xFF;
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case PTRACE_EVENT_SINGLESTEP: {
|
case PTRACE_EVENT_SINGLESTEP: {
|
||||||
struct regs regs;
|
struct URegs regs;
|
||||||
ptrace(PTRACE_GETREGS, res, NULL, ®s);
|
ptrace(PTRACE_GETREGS, res, NULL, ®s);
|
||||||
show_commandline(res, status, ®s);
|
show_commandline(res, status, ®s);
|
||||||
}
|
}
|
||||||
@ -780,7 +731,7 @@ int main(int argc, char * argv[]) {
|
|||||||
} else {
|
} else {
|
||||||
printf("Program received signal %s.\n", sig_to_str(WSTOPSIG(status)));
|
printf("Program received signal %s.\n", sig_to_str(WSTOPSIG(status)));
|
||||||
|
|
||||||
struct regs regs;
|
struct URegs regs;
|
||||||
ptrace(PTRACE_GETREGS, res, NULL, ®s);
|
ptrace(PTRACE_GETREGS, res, NULL, ®s);
|
||||||
|
|
||||||
show_commandline(res, status, ®s);
|
show_commandline(res, status, ®s);
|
||||||
|
238
apps/strace.c
238
apps/strace.c
@ -21,30 +21,11 @@
|
|||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/uregs.h>
|
||||||
#include <syscall_nums.h>
|
#include <syscall_nums.h>
|
||||||
|
|
||||||
static FILE * logfile;
|
static FILE * logfile;
|
||||||
|
|
||||||
#ifdef __x86_64__
|
|
||||||
# include <kernel/arch/x86_64/regs.h>
|
|
||||||
# define syscall_result(r) ((r)->rax)
|
|
||||||
# define syscall_num(r) ((r)->rax)
|
|
||||||
# define syscall_arg1(r) ((r)->rbx)
|
|
||||||
# define syscall_arg2(r) ((r)->rcx)
|
|
||||||
# define syscall_arg3(r) ((r)->rdx)
|
|
||||||
# define syscall_arg4(r) ((r)->rsi)
|
|
||||||
# define syscall_arg5(r) ((r)->rdi)
|
|
||||||
#elif defined(__aarch64__)
|
|
||||||
# include <kernel/arch/aarch64/regs.h>
|
|
||||||
# define syscall_result(r) ((r)->x0)
|
|
||||||
# define syscall_num(r) ((r)->x0)
|
|
||||||
# define syscall_arg1(r) ((r)->x1)
|
|
||||||
# define syscall_arg2(r) ((r)->x2)
|
|
||||||
# define syscall_arg3(r) ((r)->x3)
|
|
||||||
# define syscall_arg4(r) ((r)->x4)
|
|
||||||
# define syscall_arg5(r) ((r)->x5)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* System call names */
|
/* System call names */
|
||||||
const char * syscall_names[] = {
|
const char * syscall_names[] = {
|
||||||
[SYS_EXT] = "exit",
|
[SYS_EXT] = "exit",
|
||||||
@ -355,25 +336,6 @@ const char * signal_names[NSIG] = {
|
|||||||
M(SIGTTOU),
|
M(SIGTTOU),
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 0
|
|
||||||
static void dump_regs(struct regs * r) {
|
|
||||||
fprintf(logfile,
|
|
||||||
" $rip=0x%016lx\n"
|
|
||||||
" $rsi=0x%016lx,$rdi=0x%016lx,$rbp=0x%016lx,$rsp=0x%016lx\n"
|
|
||||||
" $rax=0x%016lx,$rbx=0x%016lx,$rcx=0x%016lx,$rdx=0x%016lx\n"
|
|
||||||
" $r8= 0x%016lx,$r9= 0x%016lx,$r10=0x%016lx,$r11=0x%016lx\n"
|
|
||||||
" $r12=0x%016lx,$r13=0x%016lx,$r14=0x%016lx,$r15=0x%016lx\n"
|
|
||||||
" cs=0x%016lx ss=0x%016lx rflags=0x%016lx int=0x%02lx err=0x%02lx\n",
|
|
||||||
r->rip,
|
|
||||||
r->rsi, r->rdi, r->rbp, r->rsp,
|
|
||||||
r->rax, r->rbx, r->rcx, r->rdx,
|
|
||||||
r->r8, r->r9, r->r10, r->r11,
|
|
||||||
r->r12, r->r13, r->r14, r->r15,
|
|
||||||
r->cs, r->ss, r->rflags, r->int_no, r->err_code
|
|
||||||
);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void open_flags(int flags) {
|
static void open_flags(int flags) {
|
||||||
if (!flags) {
|
if (!flags) {
|
||||||
fprintf(logfile, "O_RDONLY");
|
fprintf(logfile, "O_RDONLY");
|
||||||
@ -556,9 +518,9 @@ static void print_error(int err) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void maybe_errno(struct regs * r) {
|
static void maybe_errno(struct URegs * r) {
|
||||||
fprintf(logfile, ") = %ld", syscall_result(r));
|
fprintf(logfile, ") = %ld", uregs_syscall_result(r));
|
||||||
if ((intptr_t)syscall_result(r) < 0) print_error(-syscall_result(r));
|
if ((intptr_t)uregs_syscall_result(r) < 0) print_error(-uregs_syscall_result(r));
|
||||||
fprintf(logfile, "\n");
|
fprintf(logfile, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -601,121 +563,121 @@ static void signal_arg(int signum) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_syscall(pid_t pid, struct regs * r) {
|
static void handle_syscall(pid_t pid, struct URegs * r) {
|
||||||
if (syscall_num(r) >= sizeof(syscall_mask)) return;
|
if (uregs_syscall_num(r) >= sizeof(syscall_mask)) return;
|
||||||
if (!syscall_mask[syscall_num(r)]) return;
|
if (!syscall_mask[uregs_syscall_num(r)]) return;
|
||||||
|
|
||||||
fprintf(logfile, "%s(", syscall_names[syscall_num(r)]);
|
fprintf(logfile, "%s(", syscall_names[uregs_syscall_num(r)]);
|
||||||
switch (syscall_num(r)) {
|
switch (uregs_syscall_num(r)) {
|
||||||
case SYS_OPEN:
|
case SYS_OPEN:
|
||||||
string_arg(pid, syscall_arg1(r)); COMMA;
|
string_arg(pid, uregs_syscall_arg1(r)); COMMA;
|
||||||
open_flags(syscall_arg2(r));
|
open_flags(uregs_syscall_arg2(r));
|
||||||
break;
|
break;
|
||||||
case SYS_READ:
|
case SYS_READ:
|
||||||
fd_arg(pid, syscall_arg1(r)); COMMA;
|
fd_arg(pid, uregs_syscall_arg1(r)); COMMA;
|
||||||
/* Plus two more when done */
|
/* Plus two more when done */
|
||||||
break;
|
break;
|
||||||
case SYS_WRITE:
|
case SYS_WRITE:
|
||||||
fd_arg(pid, syscall_arg1(r)); COMMA;
|
fd_arg(pid, uregs_syscall_arg1(r)); COMMA;
|
||||||
buffer_arg(pid, syscall_arg2(r), syscall_arg3(r)); COMMA;
|
buffer_arg(pid, uregs_syscall_arg2(r), uregs_syscall_arg3(r)); COMMA;
|
||||||
uint_arg(syscall_arg3(r));
|
uint_arg(uregs_syscall_arg3(r));
|
||||||
break;
|
break;
|
||||||
case SYS_CLOSE:
|
case SYS_CLOSE:
|
||||||
fd_arg(pid, syscall_arg1(r));
|
fd_arg(pid, uregs_syscall_arg1(r));
|
||||||
break;
|
break;
|
||||||
case SYS_SBRK:
|
case SYS_SBRK:
|
||||||
uint_arg(syscall_arg1(r));
|
uint_arg(uregs_syscall_arg1(r));
|
||||||
break;
|
break;
|
||||||
case SYS_SEEK:
|
case SYS_SEEK:
|
||||||
fd_arg(pid, syscall_arg1(r)); COMMA;
|
fd_arg(pid, uregs_syscall_arg1(r)); COMMA;
|
||||||
int_arg(syscall_arg2(r)); COMMA;
|
int_arg(uregs_syscall_arg2(r)); COMMA;
|
||||||
switch (syscall_arg3(r)) {
|
switch (uregs_syscall_arg3(r)) {
|
||||||
case 0: fprintf(logfile, "SEEK_SET"); break;
|
case 0: fprintf(logfile, "SEEK_SET"); break;
|
||||||
case 1: fprintf(logfile, "SEEK_CUR"); break;
|
case 1: fprintf(logfile, "SEEK_CUR"); break;
|
||||||
case 2: fprintf(logfile, "SEEK_END"); break;
|
case 2: fprintf(logfile, "SEEK_END"); break;
|
||||||
default: int_arg(syscall_arg3(r)); break;
|
default: int_arg(uregs_syscall_arg3(r)); break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SYS_STATF:
|
case SYS_STATF:
|
||||||
string_arg(pid, syscall_arg1(r)); COMMA;
|
string_arg(pid, uregs_syscall_arg1(r)); COMMA;
|
||||||
pointer_arg(syscall_arg2(r));
|
pointer_arg(uregs_syscall_arg2(r));
|
||||||
break;
|
break;
|
||||||
case SYS_LSTAT:
|
case SYS_LSTAT:
|
||||||
string_arg(pid, syscall_arg1(r)); COMMA;
|
string_arg(pid, uregs_syscall_arg1(r)); COMMA;
|
||||||
pointer_arg(syscall_arg2(r));
|
pointer_arg(uregs_syscall_arg2(r));
|
||||||
break;
|
break;
|
||||||
case SYS_READDIR:
|
case SYS_READDIR:
|
||||||
fd_arg(pid, syscall_arg1(r)); COMMA;
|
fd_arg(pid, uregs_syscall_arg1(r)); COMMA;
|
||||||
int_arg(syscall_arg2(r)); COMMA;
|
int_arg(uregs_syscall_arg2(r)); COMMA;
|
||||||
pointer_arg(syscall_arg3(r));
|
pointer_arg(uregs_syscall_arg3(r));
|
||||||
break;
|
break;
|
||||||
case SYS_KILL:
|
case SYS_KILL:
|
||||||
int_arg(syscall_arg1(r)); COMMA; /* pid_arg? */
|
int_arg(uregs_syscall_arg1(r)); COMMA; /* pid_arg? */
|
||||||
int_arg(syscall_arg2(r)); /* TODO signal name */
|
int_arg(uregs_syscall_arg2(r)); /* TODO signal name */
|
||||||
break;
|
break;
|
||||||
case SYS_CHDIR:
|
case SYS_CHDIR:
|
||||||
string_arg(pid, syscall_arg1(r));
|
string_arg(pid, uregs_syscall_arg1(r));
|
||||||
break;
|
break;
|
||||||
case SYS_GETCWD:
|
case SYS_GETCWD:
|
||||||
/* output is first arg */
|
/* output is first arg */
|
||||||
pointer_arg(syscall_arg1(r)); COMMA; /* TODO syscall outputs */
|
pointer_arg(uregs_syscall_arg1(r)); COMMA; /* TODO syscall outputs */
|
||||||
uint_arg(syscall_arg2(r));
|
uint_arg(uregs_syscall_arg2(r));
|
||||||
break;
|
break;
|
||||||
case SYS_CLONE:
|
case SYS_CLONE:
|
||||||
pointer_arg(syscall_arg1(r)); COMMA;
|
pointer_arg(uregs_syscall_arg1(r)); COMMA;
|
||||||
pointer_arg(syscall_arg2(r)); COMMA;
|
pointer_arg(uregs_syscall_arg2(r)); COMMA;
|
||||||
pointer_arg(syscall_arg3(r));
|
pointer_arg(uregs_syscall_arg3(r));
|
||||||
break;
|
break;
|
||||||
case SYS_SETHOSTNAME:
|
case SYS_SETHOSTNAME:
|
||||||
string_arg(pid, syscall_arg1(r));
|
string_arg(pid, uregs_syscall_arg1(r));
|
||||||
break;
|
break;
|
||||||
case SYS_GETHOSTNAME:
|
case SYS_GETHOSTNAME:
|
||||||
/* plus one more when done */
|
/* plus one more when done */
|
||||||
break;
|
break;
|
||||||
case SYS_MKDIR:
|
case SYS_MKDIR:
|
||||||
string_arg(pid, syscall_arg1(r)); COMMA;
|
string_arg(pid, uregs_syscall_arg1(r)); COMMA;
|
||||||
uint_arg(syscall_arg2(r));
|
uint_arg(uregs_syscall_arg2(r));
|
||||||
break;
|
break;
|
||||||
case SYS_SHUTDOWN:
|
case SYS_SHUTDOWN:
|
||||||
int_arg(syscall_arg1(r)); COMMA;
|
int_arg(uregs_syscall_arg1(r)); COMMA;
|
||||||
int_arg(syscall_arg2(r));
|
int_arg(uregs_syscall_arg2(r));
|
||||||
break;
|
break;
|
||||||
case SYS_ACCESS:
|
case SYS_ACCESS:
|
||||||
string_arg(pid, syscall_arg1(r)); COMMA;
|
string_arg(pid, uregs_syscall_arg1(r)); COMMA;
|
||||||
int_arg(syscall_arg2(r));
|
int_arg(uregs_syscall_arg2(r));
|
||||||
break;
|
break;
|
||||||
case SYS_PTRACE:
|
case SYS_PTRACE:
|
||||||
switch (syscall_arg1(r)) {
|
switch (uregs_syscall_arg1(r)) {
|
||||||
C(PTRACE_ATTACH);
|
C(PTRACE_ATTACH);
|
||||||
C(PTRACE_CONT);
|
C(PTRACE_CONT);
|
||||||
C(PTRACE_DETACH);
|
C(PTRACE_DETACH);
|
||||||
C(PTRACE_TRACEME);
|
C(PTRACE_TRACEME);
|
||||||
C(PTRACE_GETREGS);
|
C(PTRACE_GETREGS);
|
||||||
C(PTRACE_PEEKDATA);
|
C(PTRACE_PEEKDATA);
|
||||||
default: int_arg(syscall_arg1(r)); break;
|
default: int_arg(uregs_syscall_arg1(r)); break;
|
||||||
} COMMA;
|
} COMMA;
|
||||||
int_arg(syscall_arg2(r)); COMMA;
|
int_arg(uregs_syscall_arg2(r)); COMMA;
|
||||||
pointer_arg(syscall_arg3(r)); COMMA;
|
pointer_arg(uregs_syscall_arg3(r)); COMMA;
|
||||||
pointer_arg(syscall_arg4(r));
|
pointer_arg(uregs_syscall_arg4(r));
|
||||||
break;
|
break;
|
||||||
case SYS_EXECVE:
|
case SYS_EXECVE:
|
||||||
string_arg(pid, syscall_arg1(r)); COMMA;
|
string_arg(pid, uregs_syscall_arg1(r)); COMMA;
|
||||||
string_array_arg(pid, syscall_arg2(r)); COMMA;
|
string_array_arg(pid, uregs_syscall_arg2(r)); COMMA;
|
||||||
pointer_arg(syscall_arg3(r));
|
pointer_arg(uregs_syscall_arg3(r));
|
||||||
break;
|
break;
|
||||||
case SYS_SHM_OBTAIN:
|
case SYS_SHM_OBTAIN:
|
||||||
string_arg(pid, syscall_arg1(r)); COMMA;
|
string_arg(pid, uregs_syscall_arg1(r)); COMMA;
|
||||||
pointer_arg(syscall_arg2(r));
|
pointer_arg(uregs_syscall_arg2(r));
|
||||||
break;
|
break;
|
||||||
case SYS_SHM_RELEASE:
|
case SYS_SHM_RELEASE:
|
||||||
string_arg(pid, syscall_arg1(r));
|
string_arg(pid, uregs_syscall_arg1(r));
|
||||||
break;
|
break;
|
||||||
case SYS_SIGNAL:
|
case SYS_SIGNAL:
|
||||||
signal_arg(syscall_arg1(r)); COMMA;
|
signal_arg(uregs_syscall_arg1(r)); COMMA;
|
||||||
pointer_arg(syscall_arg2(r));
|
pointer_arg(uregs_syscall_arg2(r));
|
||||||
break;
|
break;
|
||||||
case SYS_SYSFUNC:
|
case SYS_SYSFUNC:
|
||||||
switch (syscall_arg1(r)) {
|
switch (uregs_syscall_arg1(r)) {
|
||||||
C(TOARU_SYS_FUNC_SYNC);
|
C(TOARU_SYS_FUNC_SYNC);
|
||||||
C(TOARU_SYS_FUNC_LOGHERE);
|
C(TOARU_SYS_FUNC_LOGHERE);
|
||||||
C(TOARU_SYS_FUNC_KDEBUG);
|
C(TOARU_SYS_FUNC_KDEBUG);
|
||||||
@ -725,68 +687,68 @@ static void handle_syscall(pid_t pid, struct regs * r) {
|
|||||||
C(TOARU_SYS_FUNC_THREADNAME);
|
C(TOARU_SYS_FUNC_THREADNAME);
|
||||||
C(TOARU_SYS_FUNC_SETGSBASE);
|
C(TOARU_SYS_FUNC_SETGSBASE);
|
||||||
C(TOARU_SYS_FUNC_NPROC);
|
C(TOARU_SYS_FUNC_NPROC);
|
||||||
default: int_arg(syscall_arg1(r)); break;
|
default: int_arg(uregs_syscall_arg1(r)); break;
|
||||||
} COMMA;
|
} COMMA;
|
||||||
pointer_arg(syscall_arg2(r));
|
pointer_arg(uregs_syscall_arg2(r));
|
||||||
break;
|
break;
|
||||||
case SYS_FSWAIT:
|
case SYS_FSWAIT:
|
||||||
int_arg(syscall_arg1(r)); COMMA;
|
int_arg(uregs_syscall_arg1(r)); COMMA;
|
||||||
fds_arg(pid, syscall_arg1(r), syscall_arg2(r));
|
fds_arg(pid, uregs_syscall_arg1(r), uregs_syscall_arg2(r));
|
||||||
break;
|
break;
|
||||||
case SYS_FSWAIT2:
|
case SYS_FSWAIT2:
|
||||||
int_arg(syscall_arg1(r)); COMMA;
|
int_arg(uregs_syscall_arg1(r)); COMMA;
|
||||||
fds_arg(pid, syscall_arg1(r), syscall_arg2(r)); COMMA;
|
fds_arg(pid, uregs_syscall_arg1(r), uregs_syscall_arg2(r)); COMMA;
|
||||||
int_arg(syscall_arg3(r));
|
int_arg(uregs_syscall_arg3(r));
|
||||||
break;
|
break;
|
||||||
case SYS_FSWAIT3:
|
case SYS_FSWAIT3:
|
||||||
int_arg(syscall_arg1(r)); COMMA;
|
int_arg(uregs_syscall_arg1(r)); COMMA;
|
||||||
fds_arg(pid, syscall_arg1(r), syscall_arg2(r)); COMMA;
|
fds_arg(pid, uregs_syscall_arg1(r), uregs_syscall_arg2(r)); COMMA;
|
||||||
int_arg(syscall_arg3(r)); COMMA;
|
int_arg(uregs_syscall_arg3(r)); COMMA;
|
||||||
pointer_arg(syscall_arg4(r));
|
pointer_arg(uregs_syscall_arg4(r));
|
||||||
break;
|
break;
|
||||||
case SYS_IOCTL:
|
case SYS_IOCTL:
|
||||||
fd_arg(pid, syscall_arg1(r)); COMMA;
|
fd_arg(pid, uregs_syscall_arg1(r)); COMMA;
|
||||||
int_arg(syscall_arg2(r)); COMMA;
|
int_arg(uregs_syscall_arg2(r)); COMMA;
|
||||||
pointer_arg(syscall_arg3(r));
|
pointer_arg(uregs_syscall_arg3(r));
|
||||||
break;
|
break;
|
||||||
case SYS_WAITPID:
|
case SYS_WAITPID:
|
||||||
int_arg(syscall_arg1(r)); COMMA;
|
int_arg(uregs_syscall_arg1(r)); COMMA;
|
||||||
pointer_arg(syscall_arg2(r)); COMMA;
|
pointer_arg(uregs_syscall_arg2(r)); COMMA;
|
||||||
int_arg(syscall_arg3(r)); /* TODO waitpid options */
|
int_arg(uregs_syscall_arg3(r)); /* TODO waitpid options */
|
||||||
break;
|
break;
|
||||||
case SYS_EXT:
|
case SYS_EXT:
|
||||||
int_arg(syscall_arg1(r));
|
int_arg(uregs_syscall_arg1(r));
|
||||||
fprintf(logfile, ") = ?\n");
|
fprintf(logfile, ") = ?\n");
|
||||||
return;
|
return;
|
||||||
case SYS_UNAME:
|
case SYS_UNAME:
|
||||||
/* One output arg */
|
/* One output arg */
|
||||||
break;
|
break;
|
||||||
case SYS_SLEEPABS:
|
case SYS_SLEEPABS:
|
||||||
uint_arg(syscall_arg1(r)); COMMA;
|
uint_arg(uregs_syscall_arg1(r)); COMMA;
|
||||||
uint_arg(syscall_arg2(r));
|
uint_arg(uregs_syscall_arg2(r));
|
||||||
break;
|
break;
|
||||||
case SYS_SLEEP:
|
case SYS_SLEEP:
|
||||||
uint_arg(syscall_arg1(r)); COMMA;
|
uint_arg(uregs_syscall_arg1(r)); COMMA;
|
||||||
uint_arg(syscall_arg2(r));
|
uint_arg(uregs_syscall_arg2(r));
|
||||||
break;
|
break;
|
||||||
case SYS_PIPE:
|
case SYS_PIPE:
|
||||||
/* Arg is a pointer */
|
/* Arg is a pointer */
|
||||||
break;
|
break;
|
||||||
case SYS_DUP2:
|
case SYS_DUP2:
|
||||||
fd_arg(pid, syscall_arg1(r)); COMMA;
|
fd_arg(pid, uregs_syscall_arg1(r)); COMMA;
|
||||||
fd_arg(pid, syscall_arg2(r));
|
fd_arg(pid, uregs_syscall_arg2(r));
|
||||||
break;
|
break;
|
||||||
case SYS_MOUNT:
|
case SYS_MOUNT:
|
||||||
string_arg(pid, syscall_arg1(r)); COMMA;
|
string_arg(pid, uregs_syscall_arg1(r)); COMMA;
|
||||||
string_arg(pid, syscall_arg2(r)); COMMA;
|
string_arg(pid, uregs_syscall_arg2(r)); COMMA;
|
||||||
uint_arg(syscall_arg3(r)); COMMA;
|
uint_arg(uregs_syscall_arg3(r)); COMMA;
|
||||||
pointer_arg(syscall_arg4(r));
|
pointer_arg(uregs_syscall_arg4(r));
|
||||||
break;
|
break;
|
||||||
case SYS_UMASK:
|
case SYS_UMASK:
|
||||||
int_arg(syscall_arg1(r));
|
int_arg(uregs_syscall_arg1(r));
|
||||||
break;
|
break;
|
||||||
case SYS_UNLINK:
|
case SYS_UNLINK:
|
||||||
string_arg(pid, syscall_arg1(r));
|
string_arg(pid, uregs_syscall_arg1(r));
|
||||||
break;
|
break;
|
||||||
case SYS_GETTIMEOFDAY:
|
case SYS_GETTIMEOFDAY:
|
||||||
/* two output args */
|
/* two output args */
|
||||||
@ -794,9 +756,9 @@ static void handle_syscall(pid_t pid, struct regs * r) {
|
|||||||
case SYS_SIGACTION: break;
|
case SYS_SIGACTION: break;
|
||||||
case SYS_RECV:
|
case SYS_RECV:
|
||||||
case SYS_SEND:
|
case SYS_SEND:
|
||||||
fd_arg(pid, syscall_arg1(r)); COMMA;
|
fd_arg(pid, uregs_syscall_arg1(r)); COMMA;
|
||||||
msghdr_arg(pid, syscall_arg2(r)); COMMA;
|
msghdr_arg(pid, uregs_syscall_arg2(r)); COMMA;
|
||||||
int_arg(syscall_arg3(r));
|
int_arg(uregs_syscall_arg3(r));
|
||||||
break;
|
break;
|
||||||
/* These have no arguments: */
|
/* These have no arguments: */
|
||||||
case SYS_YIELD:
|
case SYS_YIELD:
|
||||||
@ -817,7 +779,7 @@ static void handle_syscall(pid_t pid, struct regs * r) {
|
|||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void finish_syscall(pid_t pid, int syscall, struct regs * r) {
|
static void finish_syscall(pid_t pid, int syscall, struct URegs * r) {
|
||||||
if (syscall >= (int)sizeof(syscall_mask)) return;
|
if (syscall >= (int)sizeof(syscall_mask)) return;
|
||||||
if (syscall >= 0 && !syscall_mask[syscall]) return;
|
if (syscall >= 0 && !syscall_mask[syscall]) return;
|
||||||
|
|
||||||
@ -826,29 +788,29 @@ static void finish_syscall(pid_t pid, int syscall, struct regs * r) {
|
|||||||
break; /* This is ptrace(PTRACE_TRACEME)... probably... */
|
break; /* This is ptrace(PTRACE_TRACEME)... probably... */
|
||||||
/* read() returns data in second value */
|
/* read() returns data in second value */
|
||||||
case SYS_READ:
|
case SYS_READ:
|
||||||
buffer_arg(pid, syscall_arg2(r), syscall_result(r)); COMMA;
|
buffer_arg(pid, uregs_syscall_arg2(r), uregs_syscall_result(r)); COMMA;
|
||||||
uint_arg(syscall_arg3(r));
|
uint_arg(uregs_syscall_arg3(r));
|
||||||
maybe_errno(r);
|
maybe_errno(r);
|
||||||
break;
|
break;
|
||||||
case SYS_GETHOSTNAME:
|
case SYS_GETHOSTNAME:
|
||||||
string_arg(pid, syscall_arg1(r));
|
string_arg(pid, uregs_syscall_arg1(r));
|
||||||
maybe_errno(r);
|
maybe_errno(r);
|
||||||
break;
|
break;
|
||||||
case SYS_UNAME:
|
case SYS_UNAME:
|
||||||
struct_utsname_arg(pid, syscall_arg1(r));
|
struct_utsname_arg(pid, uregs_syscall_arg1(r));
|
||||||
maybe_errno(r);
|
maybe_errno(r);
|
||||||
break;
|
break;
|
||||||
case SYS_PIPE:
|
case SYS_PIPE:
|
||||||
fds_arg(pid, 2, syscall_arg1(r));
|
fds_arg(pid, 2, uregs_syscall_arg1(r));
|
||||||
maybe_errno(r);
|
maybe_errno(r);
|
||||||
break;
|
break;
|
||||||
case SYS_GETTIMEOFDAY:
|
case SYS_GETTIMEOFDAY:
|
||||||
struct_timeval_arg(pid, syscall_arg1(r));
|
struct_timeval_arg(pid, uregs_syscall_arg1(r));
|
||||||
maybe_errno(r);
|
maybe_errno(r);
|
||||||
break;
|
break;
|
||||||
/* sbrk() returns an address */
|
/* sbrk() returns an address */
|
||||||
case SYS_SBRK:
|
case SYS_SBRK:
|
||||||
fprintf(logfile, ") = %#zx\n", syscall_result(r));
|
fprintf(logfile, ") = %#zx\n", uregs_syscall_result(r));
|
||||||
break;
|
break;
|
||||||
case SYS_EXECVE:
|
case SYS_EXECVE:
|
||||||
if (r == NULL) fprintf(logfile, ") = 0\n");
|
if (r == NULL) fprintf(logfile, ") = 0\n");
|
||||||
@ -1040,7 +1002,7 @@ int main(int argc, char * argv[]) {
|
|||||||
} else {
|
} else {
|
||||||
if (WIFSTOPPED(status)) {
|
if (WIFSTOPPED(status)) {
|
||||||
if (WSTOPSIG(status) == SIGTRAP) {
|
if (WSTOPSIG(status) == SIGTRAP) {
|
||||||
struct regs regs;
|
struct URegs regs;
|
||||||
ptrace(PTRACE_GETREGS, p, NULL, ®s);
|
ptrace(PTRACE_GETREGS, p, NULL, ®s);
|
||||||
|
|
||||||
/* Event type */
|
/* Event type */
|
||||||
@ -1048,7 +1010,7 @@ int main(int argc, char * argv[]) {
|
|||||||
switch (event) {
|
switch (event) {
|
||||||
case PTRACE_EVENT_SYSCALL_ENTER:
|
case PTRACE_EVENT_SYSCALL_ENTER:
|
||||||
if (previous_syscall == SYS_EXECVE) finish_syscall(p,SYS_EXECVE,NULL);
|
if (previous_syscall == SYS_EXECVE) finish_syscall(p,SYS_EXECVE,NULL);
|
||||||
previous_syscall = syscall_num(®s);
|
previous_syscall = uregs_syscall_num(®s);
|
||||||
handle_syscall(p, ®s);
|
handle_syscall(p, ®s);
|
||||||
break;
|
break;
|
||||||
case PTRACE_EVENT_SYSCALL_EXIT:
|
case PTRACE_EVENT_SYSCALL_EXIT:
|
||||||
|
72
base/usr/include/sys/uregs.h
Normal file
72
base/usr/include/sys/uregs.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <_cheader.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
_Begin_C_Header
|
||||||
|
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
# include <kernel/arch/x86_64/regs.h>
|
||||||
|
# define uregs_syscall_result(r) ((r)->rax)
|
||||||
|
# define uregs_syscall_num(r) ((r)->rax)
|
||||||
|
# define uregs_syscall_arg1(r) ((r)->rbx)
|
||||||
|
# define uregs_syscall_arg2(r) ((r)->rcx)
|
||||||
|
# define uregs_syscall_arg3(r) ((r)->rdx)
|
||||||
|
# define uregs_syscall_arg4(r) ((r)->rsi)
|
||||||
|
# define uregs_syscall_arg5(r) ((r)->rdi)
|
||||||
|
# define uregs_ip(r) ((r)->rip)
|
||||||
|
# define uregs_bp(r) ((r)->rbp)
|
||||||
|
# define UREGS_FMT \
|
||||||
|
" $rip=0x%016lx\n" \
|
||||||
|
" $rsi=0x%016lx,$rdi=0x%016lx,$rbp=0x%016lx,$rsp=0x%016lx\n" \
|
||||||
|
" $rax=0x%016lx,$rbx=0x%016lx,$rcx=0x%016lx,$rdx=0x%016lx\n" \
|
||||||
|
" $r8= 0x%016lx,$r9= 0x%016lx,$r10=0x%016lx,$r11=0x%016lx\n" \
|
||||||
|
" $r12=0x%016lx,$r13=0x%016lx,$r14=0x%016lx,$r15=0x%016lx\n" \
|
||||||
|
" cs=0x%016lx ss=0x%016lx rflags=0x%016lx int=0x%02lx err=0x%02lx\n"
|
||||||
|
# define UREGS_ARGS(r) \
|
||||||
|
(r)->rip, \
|
||||||
|
(r)->rsi, (r)->rdi, (r)->rbp, (r)->rsp, \
|
||||||
|
(r)->rax, (r)->rbx, (r)->rcx, (r)->rdx, \
|
||||||
|
(r)->r8, (r)->r9, (r)->r10, (r)->r11, \
|
||||||
|
(r)->r12, (r)->r13, (r)->r14, (r)->r15, \
|
||||||
|
(r)->cs, (r)->ss, (r)->rflags, (r)->int_no, (r)->err_code
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
# include <kernel/arch/aarch64/regs.h>
|
||||||
|
# define uregs_syscall_result(r) ((r)->x0)
|
||||||
|
# define uregs_syscall_num(r) ((r)->x0)
|
||||||
|
# define uregs_syscall_arg1(r) ((r)->x1)
|
||||||
|
# define uregs_syscall_arg2(r) ((r)->x2)
|
||||||
|
# define uregs_syscall_arg3(r) ((r)->x3)
|
||||||
|
# define uregs_syscall_arg4(r) ((r)->x4)
|
||||||
|
# define uregs_syscall_arg5(r) ((r)->x5)
|
||||||
|
# define uregs_ip(r) ((r)->elr)
|
||||||
|
# define uregs_bp(r) ((r)->x29)
|
||||||
|
# define UREGS_FMT \
|
||||||
|
" $x00=0x%016lx,$x01=0x%016lx,$x02=0x%016lx,$x03=0x%016lx\n" \
|
||||||
|
" $x04=0x%016lx,$x05=0x%016lx,$x06=0x%016lx,$x07=0x%016lx\n" \
|
||||||
|
" $x08=0x%016lx,$x09=0x%016lx,$x10=0x%016lx,$x11=0x%016lx\n" \
|
||||||
|
" $x12=0x%016lx,$x13=0x%016lx,$x14=0x%016lx,$x15=0x%016lx\n" \
|
||||||
|
" $x16=0x%016lx,$x17=0x%016lx,$x18=0x%016lx,$x19=0x%016lx\n" \
|
||||||
|
" $x20=0x%016lx,$x21=0x%016lx,$x22=0x%016lx,$x23=0x%016lx\n" \
|
||||||
|
" $x24=0x%016lx,$x25=0x%016lx,$x26=0x%016lx,$x27=0x%016lx\n" \
|
||||||
|
" $x28=0x%016lx,$x29=0x%016lx,$x30=0x%016lx\n" \
|
||||||
|
" sp=0x%016lx elr=0x%016lx\n"
|
||||||
|
# define UREGS_ARGS(r) \
|
||||||
|
(r)->x0, (r)->x1, (r)->x2, (r)->x3, (r)->x4, (r)->x5, (r)->x6, (r)->x7, \
|
||||||
|
(r)->x8, (r)->x9, (r)->x10, (r)->x11, (r)->x12, (r)->x13, (r)->x14, (r)->x15, \
|
||||||
|
(r)->x16, (r)->x17, (r)->x18, (r)->x19, (r)->x20, (r)->x21, (r)->x22, (r)->x23, \
|
||||||
|
(r)->x24, (r)->x25, (r)->x26, (r)->x27, (r)->x28, (r)->x29, (r)->x30, \
|
||||||
|
(r)->user_sp, (r)->elr
|
||||||
|
#else
|
||||||
|
# error Unsupported architecture
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct URegs {
|
||||||
|
struct regs;
|
||||||
|
#if defined(__aarch64__)
|
||||||
|
uint64_t elr;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
_End_C_Header
|
Loading…
Reference in New Issue
Block a user