mirror of
				https://github.com/go-delve/delve.git
				synced 2025-10-31 18:57:18 +08:00 
			
		
		
		
	 c412dcdc4f
			
		
	
	c412dcdc4f
	
	
	
		
			
			Go 1.19 also formats doc comments according to the new godoc syntax. Some of our comments, especially unexported symbols did not conform to the godoc syntax and therefore are mangled by 'go fmt'. This PR runs 'go fmt' from go1.19 on everything and manually fixes the problems. See also: https://github.com/golang/proposal/blob/master/design/51082-godocfmt.md
		
			
				
	
	
		
			96 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package native
 | ||
| 
 | ||
| import "C"
 | ||
| 
 | ||
| import (
 | ||
| 	"fmt"
 | ||
| 	"syscall"
 | ||
| 	"unsafe"
 | ||
| 
 | ||
| 	sys "golang.org/x/sys/unix"
 | ||
| 
 | ||
| 	"github.com/go-delve/delve/pkg/proc/amd64util"
 | ||
| )
 | ||
| 
 | ||
| // ptraceGetRegset returns floating point registers of the specified thread
 | ||
| // using PTRACE.
 | ||
| // See i386_linux_fetch_inferior_registers in gdb/i386-linux-nat.c.html
 | ||
| // and i386_supply_xsave in gdb/i386-tdep.c.html
 | ||
| // and Section 13.1 (and following) of Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1: Basic Architecture
 | ||
| func ptraceGetRegset(tid int) (regset amd64util.AMD64Xstate, err error) {
 | ||
| 	_, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_GETFPREGS, uintptr(tid), uintptr(0), uintptr(unsafe.Pointer(®set.AMD64PtraceFpRegs)), 0, 0)
 | ||
| 	if err == syscall.Errno(0) || err == syscall.ENODEV {
 | ||
| 		// ignore ENODEV, it just means this CPU doesn't have X87 registers (??)
 | ||
| 		err = nil
 | ||
| 	}
 | ||
| 
 | ||
| 	xstateargs := make([]byte, amd64util.AMD64XstateMaxSize())
 | ||
| 	iov := sys.Iovec{Base: &xstateargs[0], Len: uint32(len(xstateargs))}
 | ||
| 	_, _, err = syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_GETREGSET, uintptr(tid), _NT_X86_XSTATE, uintptr(unsafe.Pointer(&iov)), 0, 0)
 | ||
| 	if err != syscall.Errno(0) {
 | ||
| 		if err == syscall.ENODEV || err == syscall.EIO || err == syscall.EINVAL {
 | ||
| 			// ignore ENODEV, it just means this CPU or kernel doesn't support XSTATE, see https://github.com/go-delve/delve/issues/1022
 | ||
| 			// also ignore EIO, it means that we are running on an old kernel (pre 2.6.34) and PTRACE_GETREGSET is not implemented
 | ||
| 			// also ignore EINVAL, it means the kernel itself does not support the NT_X86_XSTATE argument (but does support PTRACE_GETREGSET)
 | ||
| 			err = nil
 | ||
| 		}
 | ||
| 		return
 | ||
| 	} else {
 | ||
| 		err = nil
 | ||
| 	}
 | ||
| 
 | ||
| 	regset.Xsave = xstateargs[:iov.Len]
 | ||
| 	err = amd64util.AMD64XstateRead(regset.Xsave, false, ®set)
 | ||
| 	return
 | ||
| }
 | ||
| 
 | ||
| // ptraceGetTls return the addr of tls by PTRACE_GET_THREAD_AREA for specify thread.
 | ||
| // See http://man7.org/linux/man-pages/man2/ptrace.2.html for detail about PTRACE_GET_THREAD_AREA.
 | ||
| // struct user_desc at https://golang.org/src/runtime/sys_linux_386.s
 | ||
| //
 | ||
| //	type UserDesc struct {
 | ||
| //		 EntryNumber uint32
 | ||
| //		 BaseAddr    uint32
 | ||
| //		 Limit       uint32
 | ||
| //		 Flag        uint32
 | ||
| //	}
 | ||
| func ptraceGetTls(gs int32, tid int) (uint32, error) {
 | ||
| 	ud := [4]uint32{}
 | ||
| 
 | ||
| 	// Gs usually is 0x33
 | ||
| 	_, _, err := syscall.Syscall6(syscall.SYS_PTRACE, sys.PTRACE_GET_THREAD_AREA, uintptr(tid), uintptr(gs>>3), uintptr(unsafe.Pointer(&ud)), 0, 0)
 | ||
| 	if err == syscall.ENODEV || err == syscall.EIO {
 | ||
| 		return 0, fmt.Errorf("%s", err)
 | ||
| 	}
 | ||
| 
 | ||
| 	return uint32(ud[1]), nil
 | ||
| }
 | ||
| 
 | ||
| // processVmRead calls process_vm_readv
 | ||
| func processVmRead(tid int, addr uintptr, data []byte) (int, error) {
 | ||
| 	len_iov := uint32(len(data))
 | ||
| 	local_iov := sys.Iovec{Base: &data[0], Len: len_iov}
 | ||
| 	remote_iov := remoteIovec{base: addr, len: uintptr(len_iov)}
 | ||
| 	p_local := uintptr(unsafe.Pointer(&local_iov))
 | ||
| 	p_remote := uintptr(unsafe.Pointer(&remote_iov))
 | ||
| 	n, _, err := syscall.Syscall6(sys.SYS_PROCESS_VM_READV, uintptr(tid), p_local, 1, p_remote, 1, 0)
 | ||
| 	if err != syscall.Errno(0) {
 | ||
| 		return 0, err
 | ||
| 	}
 | ||
| 	return int(n), nil
 | ||
| }
 | ||
| 
 | ||
| // processVmWrite calls process_vm_writev
 | ||
| func processVmWrite(tid int, addr uintptr, data []byte) (int, error) {
 | ||
| 	len_iov := uint32(len(data))
 | ||
| 	local_iov := sys.Iovec{Base: &data[0], Len: len_iov}
 | ||
| 	remote_iov := remoteIovec{base: addr, len: uintptr(len_iov)}
 | ||
| 	p_local := uintptr(unsafe.Pointer(&local_iov))
 | ||
| 	p_remote := uintptr(unsafe.Pointer(&remote_iov))
 | ||
| 	n, _, err := syscall.Syscall6(sys.SYS_PROCESS_VM_WRITEV, uintptr(tid), p_local, 1, p_remote, 1, 0)
 | ||
| 	if err != syscall.Errno(0) {
 | ||
| 		return 0, err
 | ||
| 	}
 | ||
| 	return int(n), nil
 | ||
| }
 |