diff --git a/sys/amd64/linux/linux.h b/sys/amd64/linux/linux.h --- a/sys/amd64/linux/linux.h +++ b/sys/amd64/linux/linux.h @@ -458,11 +458,15 @@ }; struct reg; +struct syscall_info; void bsd_to_linux_regset(const struct reg *b_reg, struct linux_pt_regset *l_regset); void linux_to_bsd_regset(struct reg *b_reg, const struct linux_pt_regset *l_regset); - +void linux_ptrace_get_syscall_info_machdep(const struct reg *reg, + struct syscall_info *si); +int linux_ptrace_getregs_machdep(struct thread *td, pid_t pid, + struct linux_pt_regset *l_regset); #endif /* !_AMD64_LINUX_H_ */ diff --git a/sys/amd64/linux/linux_machdep.c b/sys/amd64/linux/linux_machdep.c --- a/sys/amd64/linux/linux_machdep.c +++ b/sys/amd64/linux/linux_machdep.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -95,6 +96,8 @@ #include #include +#define LINUX_ARCH_AMD64 0xc000003e + int linux_execve(struct thread *td, struct linux_execve_args *args) { @@ -361,3 +364,51 @@ b_reg->r_fs = l_regset->fs; b_reg->r_gs = l_regset->gs; } + +void +linux_ptrace_get_syscall_info_machdep(const struct reg *reg, + struct syscall_info *si) +{ + + si->arch = LINUX_ARCH_AMD64; + si->instruction_pointer = reg->r_rip; + si->stack_pointer = reg->r_rsp; +} + +int +linux_ptrace_getregs_machdep(struct thread *td, pid_t pid, + struct linux_pt_regset *l_regset) +{ + struct ptrace_lwpinfo lwpinfo; + struct pcb *pcb; + int error; + + pcb = td->td_pcb; + if (td == curthread) + update_pcb_bases(pcb); + + l_regset->fs_base = pcb->pcb_fsbase; + l_regset->gs_base = pcb->pcb_gsbase; + + error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); + if (error != 0) { + linux_msg(td, "PT_LWPINFO failed with error %d", error); + return (error); + } + if ((lwpinfo.pl_flags & PL_FLAG_SCE) != 0) { + /* + * Undo the mangling done in exception.S:fast_syscall_common(). + */ + l_regset->r10 = l_regset->rcx; + } + if ((lwpinfo.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX)) != 0) { + /* + * In Linux, the syscall number - passed to the syscall + * as rax - is preserved in orig_rax; rax gets overwritten + * with syscall return value. + */ + l_regset->orig_rax = lwpinfo.pl_syscall_code; + } + + return (0); +} diff --git a/sys/arm64/linux/linux.h b/sys/arm64/linux/linux.h --- a/sys/arm64/linux/linux.h +++ b/sys/arm64/linux/linux.h @@ -321,10 +321,15 @@ }; struct reg; +struct syscall_info; void bsd_to_linux_regset(const struct reg *b_reg, struct linux_pt_regset *l_regset); void linux_to_bsd_regset(struct reg *b_reg, const struct linux_pt_regset *l_regset); +void linux_ptrace_get_syscall_info_machdep(const struct reg *reg, + struct syscall_info *si); +int linux_ptrace_getregs_machdep(struct thread *td, pid_t pid, + struct linux_pt_regset *l_regset); #endif /* _ARM64_LINUX_H_ */ diff --git a/sys/arm64/linux/linux_machdep.c b/sys/arm64/linux/linux_machdep.c --- a/sys/arm64/linux/linux_machdep.c +++ b/sys/arm64/linux/linux_machdep.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -50,6 +51,8 @@ #include #include +#define LINUX_ARCH_AARCH64 0xc00000b7 + /* DTrace init */ LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE); @@ -158,3 +161,22 @@ b_reg->elr = l_regset->pc; b_reg->spsr = l_regset->cpsr; } + +void +linux_ptrace_get_syscall_info_machdep(const struct reg *reg, + struct syscall_info *si) +{ + + si->arch = LINUX_ARCH_AARCH64; + si->instruction_pointer = reg->lr; + si->stack_pointer = reg->sp; +} + +int +linux_ptrace_getregs_machdep(struct thread *td __unused, pid_t pid __unused, + struct linux_pt_regset *l_regset __unused) +{ + + return (0); +} + diff --git a/sys/compat/linux/linux_misc.h b/sys/compat/linux/linux_misc.h --- a/sys/compat/linux/linux_misc.h +++ b/sys/compat/linux/linux_misc.h @@ -159,4 +159,26 @@ void linux_to_bsd_waitopts(int options, int *bsdopts); struct thread *linux_tdfind(struct thread *, lwpid_t, pid_t); +struct syscall_info { + uint8_t op; + uint32_t arch; + uint64_t instruction_pointer; + uint64_t stack_pointer; + union { + struct { + uint64_t nr; + uint64_t args[6]; + } entry; + struct { + int64_t rval; + uint8_t is_error; + } exit; + struct { + uint64_t nr; + uint64_t args[6]; + uint32_t ret_data; + } seccomp; + }; +}; + #endif /* _LINUX_MISC_H_ */ diff --git a/sys/compat/linux/linux_ptrace.c b/sys/compat/linux/linux_ptrace.c --- a/sys/compat/linux/linux_ptrace.c +++ b/sys/compat/linux/linux_ptrace.c @@ -107,9 +107,6 @@ #define LINUX_PTRACE_PEEKUSER_CS 136 #define LINUX_PTRACE_PEEKUSER_DS 184 -#define LINUX_ARCH_AMD64 0xc000003e -#define LINUX_ARCH_AARCH64 0xc00000b7 - static int map_signum(int lsig, int *bsigp) { @@ -169,28 +166,6 @@ return (status); } -struct syscall_info { - uint8_t op; - uint32_t arch; - uint64_t instruction_pointer; - uint64_t stack_pointer; - union { - struct { - uint64_t nr; - uint64_t args[6]; - } entry; - struct { - int64_t rval; - uint8_t is_error; - } exit; - struct { - uint64_t nr; - uint64_t args[6]; - uint32_t ret_data; - } seccomp; - }; -}; - static int linux_ptrace_peek(struct thread *td, pid_t pid, void *addr, void *data) { @@ -345,10 +320,6 @@ { struct reg b_reg; struct linux_pt_regset l_regset; -#ifdef __amd64__ - struct ptrace_lwpinfo lwpinfo; - struct pcb *pcb; -#endif int error; error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0); @@ -356,35 +327,9 @@ return (error); bsd_to_linux_regset(&b_reg, &l_regset); - -#ifdef __amd64__ - pcb = td->td_pcb; - if (td == curthread) - update_pcb_bases(pcb); - - l_regset.fs_base = pcb->pcb_fsbase; - l_regset.gs_base = pcb->pcb_gsbase; - - error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); - if (error != 0) { - linux_msg(td, "PT_LWPINFO failed with error %d", error); + error = linux_ptrace_getregs_machdep(td, pid, &l_regset); + if (error != 0) return (error); - } - if (lwpinfo.pl_flags & PL_FLAG_SCE) { - /* - * Undo the mangling done in exception.S:fast_syscall_common(). - */ - l_regset.r10 = l_regset.rcx; - } - if (lwpinfo.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX)) { - /* - * In Linux, the syscall number - passed to the syscall - * as rax - is preserved in orig_rax; rax gets overwritten - * with syscall return value. - */ - l_regset.orig_rax = lwpinfo.pl_syscall_code; - } -#endif error = copyout(&l_regset, (void *)data, sizeof(l_regset)); return (error); @@ -411,10 +356,6 @@ struct reg b_reg; struct linux_pt_regset l_regset; struct iovec iov; -#ifdef __amd64__ - struct ptrace_lwpinfo lwpinfo; - struct pcb *pcb; -#endif size_t len; int error; @@ -429,36 +370,9 @@ return (error); bsd_to_linux_regset(&b_reg, &l_regset); - -#ifdef __amd64__ - pcb = td->td_pcb; - if (td == curthread) - update_pcb_bases(pcb); - - l_regset.fs_base = pcb->pcb_fsbase; - l_regset.gs_base = pcb->pcb_gsbase; - - error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo)); - if (error != 0) { - linux_msg(td, "PT_LWPINFO failed with error %d", error); + error = linux_ptrace_getregs_machdep(td, pid, &l_regset); + if (error != 0) return (error); - } - if (lwpinfo.pl_flags & PL_FLAG_SCE) { - /* - * Undo the mangling done in exception.S:fast_syscall_common(). - */ - l_regset.r10 = l_regset.rcx; - } - - if (lwpinfo.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX)) { - /* - * In Linux, the syscall number - passed to the syscall - * as rax - is preserved in orig_rax; rax gets overwritten - * with syscall return value. - */ - l_regset.orig_rax = lwpinfo.pl_syscall_code; - } -#endif len = MIN(iov.iov_len, sizeof(l_regset)); error = copyout(&l_regset, (void *)iov.iov_base, len); @@ -582,17 +496,7 @@ if (error != 0) return (error); -#if defined(__amd64__) - si.arch = LINUX_ARCH_AMD64; - si.instruction_pointer = b_reg.r_rip; - si.stack_pointer = b_reg.r_rsp; -#elif defined(__aarch64__) - si.arch = LINUX_ARCH_AARCH64; - si.instruction_pointer = b_reg.lr; - si.stack_pointer = b_reg.sp; -#else -#error "unknown architecture" -#endif + linux_ptrace_get_syscall_info_machdep(&b_reg, &si); len = MIN(len, sizeof(si)); error = copyout(&si, (void *)data, len);