delve/pkg/proc/native/ptrace_linux_amd64.go
Chen bef326c6a5
proc: use CPUID to determine ZMM_Hi256 region offset (#3831)
The offset of state component i can be found via
CPUID.(EAX=0DH,ECX=i):EBX. The ZMM_Hi256 is state component 6, so we use
CPUID to enumerate the offset instead of hardcoding.

For core dumps, we guess the ZMM_Hi256 offset based on xcr0 and the
length of xsave region. The logic comes from binutils-gdb.

Fixes #3827.
2024-10-21 09:16:57 -07:00

43 lines
1.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package native
import (
"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 amd64_linux_fetch_inferior_registers in gdb/amd64-linux-nat.c.html
// and amd64_supply_xsave in gdb/amd64-tdep.c.html
// and Section 13.1 (and following) of Intel® 64 and IA-32 Architectures Software Developers 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(&regset.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: uint64(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, &regset, amd64util.AMD64XstateZMMHi256Offset())
return
}