gitlab.com/Raven-IO/raven-delve@v1.22.4/pkg/proc/native/threads_linux_amd64.go (about) 1 package native 2 3 import ( 4 "syscall" 5 "unsafe" 6 7 sys "golang.org/x/sys/unix" 8 9 "gitlab.com/Raven-IO/raven-delve/pkg/proc" 10 "gitlab.com/Raven-IO/raven-delve/pkg/proc/amd64util" 11 "gitlab.com/Raven-IO/raven-delve/pkg/proc/linutil" 12 ) 13 14 func (t *nativeThread) restoreRegisters(savedRegs proc.Registers) error { 15 sr := savedRegs.(*linutil.AMD64Registers) 16 17 var restoreRegistersErr error 18 t.dbp.execPtraceFunc(func() { 19 oldRegs := (*sys.PtraceRegs)(sr.Regs) 20 21 var currentRegs sys.PtraceRegs 22 restoreRegistersErr = sys.PtraceGetRegs(t.ID, ¤tRegs) 23 if restoreRegistersErr != nil { 24 return 25 } 26 // restoreRegisters is only supposed to restore CPU registers, not FS_BASE and GS_BASE 27 oldRegs.Fs_base = currentRegs.Fs_base 28 oldRegs.Gs_base = currentRegs.Gs_base 29 30 restoreRegistersErr = sys.PtraceSetRegs(t.ID, oldRegs) 31 32 if restoreRegistersErr != nil { 33 return 34 } 35 if sr.Fpregset.Xsave != nil { 36 iov := sys.Iovec{Base: &sr.Fpregset.Xsave[0], Len: uint64(len(sr.Fpregset.Xsave))} 37 _, _, restoreRegistersErr = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_SETREGSET, uintptr(t.ID), _NT_X86_XSTATE, uintptr(unsafe.Pointer(&iov)), 0, 0) 38 return 39 } 40 41 _, _, restoreRegistersErr = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_SETFPREGS, uintptr(t.ID), uintptr(0), uintptr(unsafe.Pointer(&sr.Fpregset.AMD64PtraceFpRegs)), 0, 0) 42 }) 43 if restoreRegistersErr == syscall.Errno(0) { 44 restoreRegistersErr = nil 45 } 46 return restoreRegistersErr 47 } 48 49 const debugRegUserOffset = 848 // offset of debug registers in the user struct, see source/arch/x86/kernel/ptrace.c 50 51 func (t *nativeThread) withDebugRegisters(f func(*amd64util.DebugRegisters) error) error { 52 var err error 53 t.dbp.execPtraceFunc(func() { 54 debugregs := make([]uint64, 8) 55 56 for i := range debugregs { 57 if i == 4 || i == 5 { 58 continue 59 } 60 _, _, err = sys.Syscall6(sys.SYS_PTRACE, sys.PTRACE_PEEKUSR, uintptr(t.ID), uintptr(debugRegUserOffset+uintptr(i)*unsafe.Sizeof(debugregs[0])), uintptr(unsafe.Pointer(&debugregs[i])), 0, 0) 61 if err != nil && err != syscall.Errno(0) { 62 return 63 } 64 } 65 66 drs := amd64util.NewDebugRegisters(&debugregs[0], &debugregs[1], &debugregs[2], &debugregs[3], &debugregs[6], &debugregs[7]) 67 68 err = f(drs) 69 70 if drs.Dirty { 71 for i := range debugregs { 72 if i == 4 || i == 5 { 73 // Linux will return EIO for DR4 and DR5 74 continue 75 } 76 _, _, err = sys.Syscall6(sys.SYS_PTRACE, sys.PTRACE_POKEUSR, uintptr(t.ID), uintptr(debugRegUserOffset+uintptr(i)*unsafe.Sizeof(debugregs[0])), uintptr(debugregs[i]), 0, 0) 77 if err != nil && err != syscall.Errno(0) { 78 return 79 } 80 } 81 } 82 }) 83 if err == syscall.Errno(0) || err == sys.ESRCH { 84 err = nil 85 } 86 return err 87 }