The branch main has been updated by trasz:

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

commit ad0379660d0c77aaf0ca6ec19472b7bb173c5794
Author:     Edward Tomasz Napierala <tr...@freebsd.org>
AuthorDate: 2021-10-29 15:18:13 +0000
Commit:     Edward Tomasz Napierala <tr...@freebsd.org>
CommitDate: 2021-10-29 15:18:28 +0000

    linux: make PTRACE_GETREGS return correct struct
    
    Previously it returned a shorter struct.  I can't find any
    modern software that uses it, but tests/ptrace from strace(1)
    repo complained.
    
    Differential Revision: https://reviews.freebsd.org/D32601
---
 sys/amd64/linux/linux_ptrace.c | 62 ++++++++++++------------------------------
 1 file changed, 18 insertions(+), 44 deletions(-)

diff --git a/sys/amd64/linux/linux_ptrace.c b/sys/amd64/linux/linux_ptrace.c
index 275450d63b2d..0f06f2aa9c5c 100644
--- a/sys/amd64/linux/linux_ptrace.c
+++ b/sys/amd64/linux/linux_ptrace.c
@@ -214,38 +214,6 @@ struct syscall_info {
        };
 };
 
-/*
- * Translate amd64 ptrace registers between Linux and FreeBSD formats.
- * The translation is pretty straighforward, for all registers but
- * orig_rax on Linux side and r_trapno and r_err in FreeBSD.
- */
-static void
-map_regs_to_linux(struct reg *b_reg, struct linux_pt_reg *l_reg)
-{
-
-       l_reg->r15 = b_reg->r_r15;
-       l_reg->r14 = b_reg->r_r14;
-       l_reg->r13 = b_reg->r_r13;
-       l_reg->r12 = b_reg->r_r12;
-       l_reg->rbp = b_reg->r_rbp;
-       l_reg->rbx = b_reg->r_rbx;
-       l_reg->r11 = b_reg->r_r11;
-       l_reg->r10 = b_reg->r_r10;
-       l_reg->r9 = b_reg->r_r9;
-       l_reg->r8 = b_reg->r_r8;
-       l_reg->rax = b_reg->r_rax;
-       l_reg->rcx = b_reg->r_rcx;
-       l_reg->rdx = b_reg->r_rdx;
-       l_reg->rsi = b_reg->r_rsi;
-       l_reg->rdi = b_reg->r_rdi;
-       l_reg->orig_rax = b_reg->r_rax;
-       l_reg->rip = b_reg->r_rip;
-       l_reg->cs = b_reg->r_cs;
-       l_reg->eflags = b_reg->r_rflags;
-       l_reg->rsp = b_reg->r_rsp;
-       l_reg->ss = b_reg->r_ss;
-}
-
 static void
 map_regs_from_linux(struct reg *b_reg, struct linux_pt_reg *l_reg)
 {
@@ -434,14 +402,21 @@ linux_ptrace_getregs(struct thread *td, pid_t pid, void 
*data)
 {
        struct ptrace_lwpinfo lwpinfo;
        struct reg b_reg;
-       struct linux_pt_reg l_reg;
+       struct linux_pt_regset l_regset;
+       struct pcb *pcb;
        int error;
 
        error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0);
        if (error != 0)
                return (error);
 
-       map_regs_to_linux(&b_reg, &l_reg);
+       pcb = td->td_pcb;
+       if (td == curthread)
+               update_pcb_bases(pcb);
+
+       bsd_to_linux_regset(&b_reg, &l_regset);
+       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) {
@@ -450,21 +425,20 @@ linux_ptrace_getregs(struct thread *td, pid_t pid, void 
*data)
        }
        if (lwpinfo.pl_flags & PL_FLAG_SCE) {
                /*
-                * The strace(1) utility depends on RAX being set to -ENOSYS
-                * on syscall entry; otherwise it loops printing those:
-                *
-                * [ Process PID=928 runs in 64 bit mode. ]
-                * [ Process PID=928 runs in x32 mode. ]
+                * Undo the mangling done in exception.S:fast_syscall_common().
                 */
-               l_reg.rax = -38; /* -ENOSYS */
-
+               l_regset.r10 = l_regset.rcx;
+       }
+       if (lwpinfo.pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX)) {
                /*
-                * Undo the mangling done in exception.S:fast_syscall_common().
+                * In Linux, the syscall number - passed to the syscall
+                * as rax - is preserved in orig_rax; rax gets overwritten
+                * with syscall return value.
                 */
-               l_reg.r10 = l_reg.rcx;
+               l_regset.orig_rax = lwpinfo.pl_syscall_code;
        }
 
-       error = copyout(&l_reg, (void *)data, sizeof(l_reg));
+       error = copyout(&l_regset, (void *)data, sizeof(l_regset));
        return (error);
 }
 

Reply via email to