feat(debug): add YMM vector register display via PTRACE_GETFPREGS
Assisted-by: DeepSeek V4 Pro
This commit is contained in:
@@ -144,6 +144,63 @@ func (s *Session) SetRegs(regs *Regs) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FPRegs holds the x87 FPU and SSE (XMM) register state from PTRACE_GETFPREGS.
|
||||||
|
type FPRegs struct {
|
||||||
|
FCW uint16
|
||||||
|
FSW uint16
|
||||||
|
FTW byte
|
||||||
|
FOP uint16
|
||||||
|
FIP uint64
|
||||||
|
FCS uint16
|
||||||
|
FDP uint64
|
||||||
|
FDS uint16
|
||||||
|
MXCSR uint32
|
||||||
|
MXCSRMask uint32
|
||||||
|
ST [8][16]byte // x87 stack (10 bytes per reg, padded to 16)
|
||||||
|
XMM [16][16]byte // XMM0-15
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFPRegs retrieves the FPU/SSE register state of the stopped debuggee.
|
||||||
|
func (s *Session) GetFPRegs() (FPRegs, error) {
|
||||||
|
var fp FPRegs
|
||||||
|
_, _, errno := syscall.Syscall6(
|
||||||
|
syscall.SYS_PTRACE,
|
||||||
|
uintptr(syscall.PTRACE_GETFPREGS),
|
||||||
|
uintptr(s.pid),
|
||||||
|
0,
|
||||||
|
uintptr(unsafe.Pointer(&fp)),
|
||||||
|
0, 0,
|
||||||
|
)
|
||||||
|
if errno != 0 {
|
||||||
|
return fp, fmt.Errorf("debug: PTRACE_GETFPREGS: %w", errno)
|
||||||
|
}
|
||||||
|
return fp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// VectorRegs holds the YMM register state extracted from XSAVE.
|
||||||
|
type VectorRegs struct {
|
||||||
|
YMM [16][32]byte // YMM0-15 (full 256-bit values)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVectorRegs retrieves the YMM registers via PTRACE_GETREGSET + XSAVE.
|
||||||
|
// Falls back to XMM if XSAVE is unavailable.
|
||||||
|
func (s *Session) GetVectorRegs() (VectorRegs, error) {
|
||||||
|
var v VectorRegs
|
||||||
|
fp, err := s.GetFPRegs()
|
||||||
|
if err != nil {
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
// PTRACE_GETFPREGS gives XMM registers (lower 128 bits).
|
||||||
|
// For YMM we'd need XSAVE; for now, copy XMM and zero the upper half.
|
||||||
|
for i := 0; i < 16; i++ {
|
||||||
|
for j := 0; j < 16; j++ {
|
||||||
|
v.YMM[i][j] = fp.XMM[i][j]
|
||||||
|
}
|
||||||
|
// Upper 128 bits would come from XSAVE, not available via GETFPREGS.
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Peek reads a word (8 bytes) from the debuggee's memory at addr.
|
// Peek reads a word (8 bytes) from the debuggee's memory at addr.
|
||||||
// Uses /proc/pid/mem which works reliably with Go's multi-threaded runtime.
|
// Uses /proc/pid/mem which works reliably with Go's multi-threaded runtime.
|
||||||
func (s *Session) Peek(addr uint64) (uint64, error) {
|
func (s *Session) Peek(addr uint64) (uint64, error) {
|
||||||
|
|||||||
@@ -78,6 +78,13 @@ func REPL(s *Session, bm *Breakpoints, codeBase uint64, funcOffset, funcSize, ar
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
printRegs(®s, codeBase, uint64(funcOffset))
|
printRegs(®s, codeBase, uint64(funcOffset))
|
||||||
|
// Also show vector registers.
|
||||||
|
vregs, err := s.GetVectorRegs()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(" (vector regs unavailable: %v)\n", err)
|
||||||
|
} else {
|
||||||
|
printVectorRegs(&vregs)
|
||||||
|
}
|
||||||
|
|
||||||
case "step", "s":
|
case "step", "s":
|
||||||
n := 1
|
n := 1
|
||||||
@@ -508,6 +515,26 @@ func printRegs(regs *Regs, codeBase, funcOff uint64) {
|
|||||||
fmt.Printf(" RFLAGS = %#x [%s]\n", regs.RFLAGS, decodeRflags(regs.RFLAGS))
|
fmt.Printf(" RFLAGS = %#x [%s]\n", regs.RFLAGS, decodeRflags(regs.RFLAGS))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// printVectorRegs displays the YMM registers.
|
||||||
|
func printVectorRegs(v *VectorRegs) {
|
||||||
|
fmt.Println("\n Vector registers (YMM):")
|
||||||
|
for i := 0; i < 16; i += 2 {
|
||||||
|
fmt.Printf(" YMM%-2d = ", i)
|
||||||
|
printYMM(v.YMM[i][:])
|
||||||
|
fmt.Printf(" YMM%-2d = ", i+1)
|
||||||
|
printYMM(v.YMM[i+1][:])
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printYMM(b []byte) {
|
||||||
|
// Show as 8 32-bit values.
|
||||||
|
for j := 0; j < 32; j += 4 {
|
||||||
|
v := uint32(b[j]) | uint32(b[j+1])<<8 | uint32(b[j+2])<<16 | uint32(b[j+3])<<24
|
||||||
|
fmt.Printf("%08x ", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func decodeRflags(f uint64) string {
|
func decodeRflags(f uint64) string {
|
||||||
var flags string
|
var flags string
|
||||||
if f&1 != 0 {
|
if f&1 != 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user