git: 0bf8d5d5f434 - main - linux: Replace ifdefs in ptrace with per-architecture callbacks

From: Edward Tomasz Napierala <trasz_at_FreeBSD.org>
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);