diff --git a/umvu/include/ptrace_defs.h b/umvu/include/ptrace_defs.h index 3b5781d..c67dc39 100644 --- a/umvu/include/ptrace_defs.h +++ b/umvu/include/ptrace_defs.h @@ -26,12 +26,43 @@ snprintf(errmsg, 80, "%s line %d, ptrace", __FILE__, __LINE__); \ perror(errmsg); \ } - +#if defined(__aarch64__) +#define P_GETREGS(tracee_tid, regs) \ + do { \ + struct iovec iov = { .iov_base = regs, .iov_len = sizeof(arch_regs_struct), }; \ + long err; \ + if (!(err = r_ptrace(PTRACE_GETREGSET, tracee_tid, NT_PRSTATUS, &iov))) { \ + iov.iov_base += sizeof (struct user_regs_struct); \ + iov.iov_len = sizeof(int); \ + err = r_ptrace(PTRACE_GETREGSET, tracee_tid, NT_ARM_SYSTEM_CALL, &iov); } \ + if (err == -1) { \ + char errmsg[80]; \ + snprintf(errmsg, 80, "%s line %d, ptrace", __FILE__, __LINE__); \ + perror(errmsg); \ + pthread_exit(NULL); \ + } \ + } while(0) +#define P_SETREGS(tracee_tid, regs) \ + do { \ + struct iovec iov = { .iov_base = regs, .iov_len = sizeof(arch_regs_struct), }; \ + long err; \ + if (!(err = r_ptrace(PTRACE_SETREGSET, tracee_tid, NT_PRSTATUS, &iov))) { \ + iov.iov_base += sizeof (struct user_regs_struct); \ + iov.iov_len = sizeof(int); \ + err = r_ptrace(PTRACE_SETREGSET, tracee_tid, NT_ARM_SYSTEM_CALL, &iov); } \ + if (err == -1) { \ + char errmsg[80]; \ + snprintf(errmsg, 80, "%s line %d, ptrace", __FILE__, __LINE__); \ + perror(errmsg); \ + pthread_exit(NULL); \ + } \ + } while(0) +#else #define P_GETREGS(tracee_tid, regs) \ PTRACE(PTRACE_GETREGSET, tracee_tid, NT_PRSTATUS, &((struct iovec) {regs, sizeof(arch_regs_struct)})) #define P_SETREGS(tracee_tid, regs) \ PTRACE(PTRACE_SETREGSET, tracee_tid, NT_PRSTATUS, &((struct iovec) {regs, sizeof(arch_regs_struct)})) - +#endif #define P_SYSCALL(tracee_tid, signal) PTRACE(PTRACE_SYSCALL, tracee_tid, 0L, signal) #define P_CONT(tracee_tid, signal) PTRACE(PTRACE_CONT, tracee_tid, 0L, signal) #define P_LISTEN(tracee_tid, signal) PTRACE(PTRACE_LISTEN, tracee_tid, 0L, signal) @@ -43,13 +74,44 @@ #define P_SETOPT(tracee_tid, opt) PTRACE(PTRACE_SETOPTIONS, tracee_tid, 0L, opt) #define P_GETEVENTMSG(tracee_tid, event) \ PTRACE(PTRACE_GETEVENTMSG, tracee_tid, 0L, event) - +#if defined(__aarch64__) +#define P_GETREGS_NODIE(tracee_tid, regs) \ + do { \ + struct iovec iov = { .iov_base = regs, .iov_len = sizeof(arch_regs_struct), }; \ + long err; \ + if (!(err = r_ptrace(PTRACE_GETREGSET, tracee_tid, NT_PRSTATUS, &iov))) { \ + iov.iov_base += sizeof (struct user_regs_struct); \ + iov.iov_len = sizeof(int); \ + err = r_ptrace(PTRACE_GETREGSET, tracee_tid, NT_ARM_SYSTEM_CALL, &iov); } \ + if (err == -1) { \ + char errmsg[80]; \ + snprintf(errmsg, 80, "%s line %d, ptrace", __FILE__, __LINE__); \ + perror(errmsg); \ + } \ + } while(0) +#define P_SETREGS_NODIE(tracee_tid, regs) \ + do { \ + struct iovec iov = { .iov_base = regs, .iov_len = sizeof(arch_regs_struct), }; \ + long err; \ + if (!(err = r_ptrace(PTRACE_SETREGSET, tracee_tid, NT_PRSTATUS, &iov))) { \ + iov.iov_base += sizeof (struct user_regs_struct); \ + iov.iov_len = sizeof(int); \ + err = r_ptrace(PTRACE_SETREGSET, tracee_tid, NT_ARM_SYSTEM_CALL, &iov); } \ + if (err == -1) { \ + char errmsg[80]; \ + snprintf(errmsg, 80, "%s line %d, ptrace", __FILE__, __LINE__); \ + perror(errmsg); \ + pthread_exit(NULL); \ + } \ + } while(0) +#else #define P_GETREGS_NODIE(tracee_tid, regs) \ PTRACE_NODIE(PTRACE_GETREGSET, tracee_tid, NT_PRSTATUS, \ &((struct iovec) {regs, sizeof(arch_regs_struct)})) #define P_SETREGS_NODIE(tracee_tid, regs) \ PTRACE_NODIE(PTRACE_SETREGSET, tracee_tid, NT_PRSTATUS, \ &((struct iovec) {regs, sizeof(arch_regs_struct)})) +#endif #define P_SYSCALL_NODIE(tracee_tid, signal) \ PTRACE_NODIE(PTRACE_SYSCALL, tracee_tid, 0L, signal) #define P_CONT_NODIE(tracee_tid, signal) \ diff --git a/umvu/include/umvu_peekpoke.h b/umvu/include/umvu_peekpoke.h index 657846b..c3463b5 100644 --- a/umvu/include/umvu_peekpoke.h +++ b/umvu/include/umvu_peekpoke.h @@ -17,13 +17,34 @@ typedef struct user_regs_struct arch_regs_struct; #elif defined(__riscv_xlen) && __riscv_xlen == 64 -#include +#include #define SYSCALL_ARG_NR 6 typedef unsigned long int syscall_arg_t; #define SYSCALL_INSTRUCTION_LEN 4 typedef struct user_regs_struct arch_regs_struct; +#elif defined(__aarch64__) + +#include +#define SYSCALL_ARG_NR 6 +typedef unsigned long int syscall_arg_t; +#define SYSCALL_INSTRUCTION_LEN 4 +struct arch_regs_struct_full { + union { + struct user_regs_struct user_regs; + struct { + unsigned long regs[31]; + unsigned long sp; + unsigned long pc; + unsigned long pstate; + }; + }; + int syscallno; +}; +typedef struct arch_regs_struct_full arch_regs_struct; +//typedef struct user_regs_struct arch_regs_struct; + #else #error Unsupported architecture diff --git a/umvu/src/umvu_peekpoke.c b/umvu/src/umvu_peekpoke.c index 540429e..42218ad 100644 --- a/umvu/src/umvu_peekpoke.c +++ b/umvu/src/umvu_peekpoke.c @@ -166,6 +166,73 @@ int umvu_poke_syscall(arch_regs_struct *regs, return 0; } +#elif defined(__aarch64__) + +void umvu_peek_syscall(arch_regs_struct *regs, + struct syscall_descriptor_t *syscall_desc, + peekpokeop_t op) +{ + if (regs && syscall_desc) { + if (op == PEEK_ARGS) { + syscall_desc->orig_syscall_number = + syscall_desc->syscall_number = regs->syscallno; + syscall_desc->syscall_args[0] = regs->regs[0]; + syscall_desc->syscall_args[1] = regs->regs[1]; + syscall_desc->syscall_args[2] = regs->regs[2]; + syscall_desc->syscall_args[3] = regs->regs[3]; + syscall_desc->syscall_args[4] = regs->regs[4]; + syscall_desc->syscall_args[5] = regs->regs[5]; + syscall_desc->prog_counter = regs->pc; + syscall_desc->stack_pointer = regs->sp; + } else { + syscall_desc->orig_ret_value = regs->regs[0]; + } + } +} + +int umvu_poke_syscall(arch_regs_struct *regs, + struct syscall_descriptor_t *syscall_desc, + peekpokeop_t op) +{ + if (regs && syscall_desc) { + switch (op) { + case POKE_ARGS: + /* regs->sp is missing as stack pointer should not be modified */ + if (regs->syscallno == (unsigned) syscall_desc->syscall_number && + regs->regs[0] == syscall_desc->syscall_args[0] && + regs->regs[1] == syscall_desc->syscall_args[1] && + regs->regs[2] == syscall_desc->syscall_args[2] && + regs->regs[3] == syscall_desc->syscall_args[3] && + regs->regs[4] == syscall_desc->syscall_args[4] && + regs->regs[5] == syscall_desc->syscall_args[5] && + regs->pc == syscall_desc->prog_counter) + return 0; + + regs->syscallno = regs->regs[8] = syscall_desc->syscall_number; + regs->regs[0] = syscall_desc->syscall_args[0]; + regs->regs[1] = syscall_desc->syscall_args[1]; + regs->regs[2] = syscall_desc->syscall_args[2]; + regs->regs[3] = syscall_desc->syscall_args[3]; + regs->regs[4] = syscall_desc->syscall_args[4]; + regs->regs[5] = syscall_desc->syscall_args[5]; + regs->pc = syscall_desc->prog_counter; + break; + case POKE_RETVALUE: + if (regs->regs[0] == syscall_desc->ret_value) + return 0; + regs->regs[0] = syscall_desc->ret_value; + break; + case SKIP_SETRETVALUE: + regs->regs[8] = -1; + regs->regs[0] = syscall_desc->ret_value; + break; + } + return 1; + } else { + return 0; + } +} + #else #error Unsupported architecture