git: 0bf8d5d5f434 - main - linux: Replace ifdefs in ptrace with per-architecture callbacks
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 09 Nov 2021 12:00:37 UTC
The branch main has been updated by trasz: URL: https://cgit.FreeBSD.org/src/commit/?id=0bf8d5d5f43426321940e351939b0b712f28b08f commit 0bf8d5d5f43426321940e351939b0b712f28b08f Author: Edward Tomasz Napierala <trasz@FreeBSD.org> AuthorDate: 2021-11-09 11:54:06 +0000 Commit: Edward Tomasz Napierala <trasz@FreeBSD.org> CommitDate: 2021-11-09 11:59:17 +0000 linux: Replace ifdefs in ptrace with per-architecture callbacks It's a cleanup; no (intended) functional changes. Sponsored By: EPSRC Reviewed By: kib Differential Revision: https://reviews.freebsd.org/D32888 --- sys/amd64/linux/linux.h | 6 ++- sys/amd64/linux/linux_machdep.c | 51 +++++++++++++++++++ sys/arm64/linux/linux.h | 5 ++ sys/arm64/linux/linux_machdep.c | 22 +++++++++ sys/compat/linux/linux_misc.h | 22 +++++++++ sys/compat/linux/linux_ptrace.c | 106 ++-------------------------------------- 6 files changed, 110 insertions(+), 102 deletions(-) diff --git a/sys/amd64/linux/linux.h b/sys/amd64/linux/linux.h index 16fe3793eae7..920ca98ce01b 100644 --- a/sys/amd64/linux/linux.h +++ b/sys/amd64/linux/linux.h @@ -458,11 +458,15 @@ struct linux_pt_regset { }; 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 index e2346f68da3a..67429a1c049f 100644 --- a/sys/amd64/linux/linux_machdep.c +++ b/sys/amd64/linux/linux_machdep.c @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include <sys/mutex.h> #include <sys/priv.h> #include <sys/proc.h> +#include <sys/ptrace.h> #include <sys/resource.h> #include <sys/resourcevar.h> #include <sys/sched.h> @@ -95,6 +96,8 @@ __FBSDID("$FreeBSD$"); #include <compat/linux/linux_signal.h> #include <compat/linux/linux_util.h> +#define LINUX_ARCH_AMD64 0xc000003e + int linux_execve(struct thread *td, struct linux_execve_args *args) { @@ -361,3 +364,51 @@ linux_to_bsd_regset(struct reg *b_reg, const struct linux_pt_regset *l_regset) 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 index 05e5bd189b36..d43795a71a83 100644 --- a/sys/arm64/linux/linux.h +++ b/sys/arm64/linux/linux.h @@ -321,10 +321,15 @@ struct linux_pt_regset { }; 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 index 0bcc05ff06de..89b7099dc752 100644 --- a/sys/arm64/linux/linux_machdep.c +++ b/sys/arm64/linux/linux_machdep.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include <sys/imgact.h> #include <sys/ktr.h> #include <sys/proc.h> +#include <sys/ptrace.h> #include <sys/reg.h> #include <sys/sdt.h> @@ -50,6 +51,8 @@ __FBSDID("$FreeBSD$"); #include <compat/linux/linux_mmap.h> #include <compat/linux/linux_util.h> +#define LINUX_ARCH_AARCH64 0xc00000b7 + /* DTrace init */ LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE); @@ -158,3 +161,22 @@ linux_to_bsd_regset(struct reg *b_reg, const struct linux_pt_regset *l_regset) 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 index bf8f3dd2f0cd..3bfc9843cda2 100644 --- a/sys/compat/linux/linux_misc.h +++ b/sys/compat/linux/linux_misc.h @@ -159,4 +159,26 @@ int linux_ptrace_status(struct thread *td, int pid, int status); 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 index 5910e4ec3d4f..4e171c77e8ab 100644 --- a/sys/compat/linux/linux_ptrace.c +++ b/sys/compat/linux/linux_ptrace.c @@ -107,9 +107,6 @@ __FBSDID("$FreeBSD$"); #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 @@ linux_ptrace_status(struct thread *td, pid_t pid, int status) 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 @@ linux_ptrace_getregs(struct thread *td, pid_t pid, void *data) { 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 @@ linux_ptrace_getregs(struct thread *td, pid_t pid, void *data) 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 @@ linux_ptrace_getregset_prstatus(struct thread *td, pid_t pid, l_ulong data) 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 @@ linux_ptrace_getregset_prstatus(struct thread *td, pid_t pid, l_ulong data) 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 @@ linux_ptrace_get_syscall_info(struct thread *td, pid_t pid, 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);