Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 02 Jun 2026 07:26:24 +0000
From:      Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Cc:        Ricardo Branco <rbranco@suse.de>
Subject:   git: c515e6040614 - main - linux: Implement PTRACE_GETREGSET NT_PRFPREG and NT_X86_XSTATE
Message-ID:  <6a1e85a0.21f2c.479eced8@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by pouria:

URL: https://cgit.FreeBSD.org/src/commit/?id=c515e6040614434a9262ee8b5ac54b81476ec7ff

commit c515e6040614434a9262ee8b5ac54b81476ec7ff
Author:     Ricardo Branco <rbranco@suse.de>
AuthorDate: 2026-04-26 14:45:35 +0000
Commit:     Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org>
CommitDate: 2026-06-02 07:25:37 +0000

    linux: Implement PTRACE_GETREGSET NT_PRFPREG and NT_X86_XSTATE
    
    Implement NT_PRFPREG and NT_X86_XSTATE for PTRACE_GETREGSET on amd64.
    Chrome's crashpad handler uses these to collect floating-point and
    extended CPU register state for crash dumps.
    
    Other architectures retain the previous EINVAL stub behavior.
    
    Signed-off-by:  Ricardo Branco <rbranco@suse.de>
    PR:             289285
    Reviewed by:    kib
    Pull-Request:   https://github.com/freebsd/freebsd-src/pull/2165
---
 sys/compat/linux/linux_ptrace.c | 91 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 85 insertions(+), 6 deletions(-)

diff --git a/sys/compat/linux/linux_ptrace.c b/sys/compat/linux/linux_ptrace.c
index 0dbfd2177122..28a4c42190af 100644
--- a/sys/compat/linux/linux_ptrace.c
+++ b/sys/compat/linux/linux_ptrace.c
@@ -335,6 +335,87 @@ linux_ptrace_getregset_prstatus(struct thread *td, pid_t pid, l_ulong data)
 	return (error);
 }
 
+#ifdef __amd64__
+static int
+linux_ptrace_getregset_prfpreg(struct thread *td, pid_t pid, l_ulong data)
+{
+	struct fpreg b_fpreg;
+	struct linux_pt_fpregset l_fpregset;
+	struct iovec iov;
+	size_t len;
+	int error;
+
+	error = copyin((const void *)data, &iov, sizeof(iov));
+	if (error != 0) {
+		linux_msg(td, "copyin error %d", error);
+		return (error);
+	}
+
+	error = kern_ptrace(td, PT_GETFPREGS, pid, &b_fpreg, 0);
+	if (error != 0)
+		return (error);
+
+	bsd_to_linux_fpregset(&b_fpreg, &l_fpregset);
+
+	len = MIN(iov.iov_len, sizeof(l_fpregset));
+	error = copyout(&l_fpregset, iov.iov_base, len);
+	if (error != 0) {
+		linux_msg(td, "copyout error %d", error);
+		return (error);
+	}
+
+	iov.iov_len = len;
+	error = copyout(&iov, (void *)data, sizeof(iov));
+	if (error != 0)
+		linux_msg(td, "iov copyout error %d", error);
+
+	return (error);
+}
+
+static int
+linux_ptrace_getregset_xstate(struct thread *td, pid_t pid, l_ulong data)
+{
+	struct ptrace_xstate_info info;
+	struct iovec iov;
+	void *xstate;
+	size_t len;
+	int error;
+
+	error = copyin((const void *)data, &iov, sizeof(iov));
+	if (error != 0) {
+		linux_msg(td, "copyin error %d", error);
+		return (error);
+	}
+
+	error = kern_ptrace(td, PT_GETXSTATE_INFO, pid, &info, sizeof(info));
+	if (error != 0)
+		return (error);
+
+	xstate = malloc(info.xsave_len, M_LINUX, M_WAITOK | M_ZERO);
+
+	error = kern_ptrace(td, PT_GETXSTATE, pid, xstate, info.xsave_len);
+	if (error != 0) {
+		free(xstate, M_LINUX);
+		return (error);
+	}
+
+	len = MIN(iov.iov_len, info.xsave_len);
+	error = copyout(xstate, iov.iov_base, len);
+	free(xstate, M_LINUX);
+	if (error != 0) {
+		linux_msg(td, "copyout error %d", error);
+		return (error);
+	}
+
+	iov.iov_len = len;
+	error = copyout(&iov, (void *)data, sizeof(iov));
+	if (error != 0)
+		linux_msg(td, "iov copyout error %d", error);
+
+	return (error);
+}
+#endif /* __amd64__ */
+
 static int
 linux_ptrace_getregset(struct thread *td, pid_t pid, l_ulong addr, l_ulong data)
 {
@@ -342,14 +423,12 @@ linux_ptrace_getregset(struct thread *td, pid_t pid, l_ulong addr, l_ulong data)
 	switch (addr) {
 	case LINUX_NT_PRSTATUS:
 		return (linux_ptrace_getregset_prstatus(td, pid, data));
+#ifdef __amd64__
 	case LINUX_NT_PRFPREG:
-		linux_msg(td, "PTRAGE_GETREGSET NT_PRFPREG not implemented; "
-		    "returning EINVAL");
-		return (EINVAL);
+		return (linux_ptrace_getregset_prfpreg(td, pid, data));
 	case LINUX_NT_X86_XSTATE:
-		linux_msg(td, "PTRAGE_GETREGSET NT_X86_XSTATE not implemented; "
-		    "returning EINVAL");
-		return (EINVAL);
+		return (linux_ptrace_getregset_xstate(td, pid, data));
+#endif
 	default:
 		linux_msg(td, "PTRACE_GETREGSET request %#lx not implemented; "
 		    "returning EINVAL", addr);


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a1e85a0.21f2c.479eced8>