gitlab.com/Raven-IO/raven-delve@v1.22.4/pkg/proc/native/ptrace_linux_386.go (about) 1 package native 2 3 import ( 4 "fmt" 5 "syscall" 6 "unsafe" 7 8 sys "golang.org/x/sys/unix" 9 10 "gitlab.com/Raven-IO/raven-delve/pkg/proc/amd64util" 11 ) 12 13 // ptraceGetRegset returns floating point registers of the specified thread 14 // using PTRACE. 15 // See i386_linux_fetch_inferior_registers in gdb/i386-linux-nat.c.html 16 // and i386_supply_xsave in gdb/i386-tdep.c.html 17 // and Section 13.1 (and following) of Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1: Basic Architecture 18 func ptraceGetRegset(tid int) (regset amd64util.AMD64Xstate, err error) { 19 _, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_GETFPREGS, uintptr(tid), uintptr(0), uintptr(unsafe.Pointer(®set.AMD64PtraceFpRegs)), 0, 0) 20 if err == syscall.Errno(0) || err == syscall.ENODEV { 21 // ignore ENODEV, it just means this CPU doesn't have X87 registers (??) 22 err = nil 23 } 24 25 xstateargs := make([]byte, amd64util.AMD64XstateMaxSize()) 26 iov := sys.Iovec{Base: &xstateargs[0], Len: uint32(len(xstateargs))} 27 _, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_GETREGSET, uintptr(tid), _NT_X86_XSTATE, uintptr(unsafe.Pointer(&iov)), 0, 0) 28 if err != syscall.Errno(0) { 29 if err == syscall.ENODEV || err == syscall.EIO || err == syscall.EINVAL { 30 // ignore ENODEV, it just means this CPU or kernel doesn't support XSTATE, see https://gitlab.com/Raven-IO/raven-delve/issues/1022 31 // also ignore EIO, it means that we are running on an old kernel (pre 2.6.34) and PTRACE_GETREGSET is not implemented 32 // also ignore EINVAL, it means the kernel itself does not support the NT_X86_XSTATE argument (but does support PTRACE_GETREGSET) 33 err = nil 34 } 35 return 36 } else { 37 err = nil 38 } 39 40 regset.Xsave = xstateargs[:iov.Len] 41 err = amd64util.AMD64XstateRead(regset.Xsave, false, ®set) 42 return 43 } 44 45 // ptraceGetTls return the addr of tls by PTRACE_GET_THREAD_AREA for specify thread. 46 // See http://man7.org/linux/man-pages/man2/ptrace.2.html for detail about PTRACE_GET_THREAD_AREA. 47 // struct user_desc at https://golang.org/src/runtime/sys_linux_386.s 48 // 49 // type UserDesc struct { 50 // EntryNumber uint32 51 // BaseAddr uint32 52 // Limit uint32 53 // Flag uint32 54 // } 55 func ptraceGetTls(gs int32, tid int) (uint32, error) { 56 ud := [4]uint32{} 57 58 // Gs usually is 0x33 59 _, _, err := syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_GET_THREAD_AREA, uintptr(tid), uintptr(gs>>3), uintptr(unsafe.Pointer(&ud)), 0, 0) 60 if err == syscall.ENODEV || err == syscall.EIO { 61 return 0, fmt.Errorf("%s", err) 62 } 63 64 return uint32(ud[1]), nil 65 } 66 67 // processVmRead calls process_vm_readv 68 func processVmRead(tid int, addr uintptr, data []byte) (int, error) { 69 len_iov := uint32(len(data)) 70 local_iov := sys.Iovec{Base: &data[0], Len: len_iov} 71 remote_iov := remoteIovec{base: addr, len: uintptr(len_iov)} 72 n, _, err := syscall.Syscall6(sys.SYS_PROCESS_VM_READV, uintptr(tid), uintptr(unsafe.Pointer(&local_iov)), 1, uintptr(unsafe.Pointer(&remote_iov)), 1, 0) 73 if err != syscall.Errno(0) { 74 return 0, err 75 } 76 return int(n), nil 77 } 78 79 // processVmWrite calls process_vm_writev 80 func processVmWrite(tid int, addr uintptr, data []byte) (int, error) { 81 len_iov := uint32(len(data)) 82 local_iov := sys.Iovec{Base: &data[0], Len: len_iov} 83 remote_iov := remoteIovec{base: addr, len: uintptr(len_iov)} 84 n, _, err := syscall.Syscall6(sys.SYS_PROCESS_VM_WRITEV, uintptr(tid), uintptr(unsafe.Pointer(&local_iov)), 1, uintptr(unsafe.Pointer(&remote_iov)), 1, 0) 85 if err != syscall.Errno(0) { 86 return 0, err 87 } 88 return int(n), nil 89 }