Files

115 lines
2.8 KiB
Go
Raw Permalink Normal View History

2026-09-25 21:46:40 +02:00
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: BSD-3-Clause
//go:build freebsd && arm64
package debug
import (
"fmt"
"golang.org/x/sys/unix"
)
// GetRegs reads the general-purpose registers of the stopped debuggee and
// converts the FreeBSD struct reg (x[30], lr, sp, elr, spsr) into the
// portable layout.
func (s *Session) GetRegs() (Regs, error) {
var ur unix.Reg
if err := unix.PtraceGetRegs(s.pid, &ur); err != nil {
return Regs{}, fmt.Errorf("debug: PT_GETREGS: %w", err)
}
return Regs{
X0: ur.X[0],
X1: ur.X[1],
X2: ur.X[2],
X3: ur.X[3],
X4: ur.X[4],
X5: ur.X[5],
X6: ur.X[6],
X7: ur.X[7],
X8: ur.X[8],
X9: ur.X[9],
X10: ur.X[10],
X11: ur.X[11],
X12: ur.X[12],
X13: ur.X[13],
X14: ur.X[14],
X15: ur.X[15],
X16: ur.X[16],
X17: ur.X[17],
X18: ur.X[18],
X19: ur.X[19],
X20: ur.X[20],
X21: ur.X[21],
X22: ur.X[22],
X23: ur.X[23],
X24: ur.X[24],
X25: ur.X[25],
X26: ur.X[26],
X27: ur.X[27],
X28: ur.X[28],
X29: ur.X[29],
X30: ur.Lr,
SP: ur.Sp,
PC: ur.Elr,
PSTATE: uint64(ur.Spsr),
}, nil
}
// SetRegs writes the general-purpose registers of the stopped debuggee.
func (s *Session) SetRegs(regs *Regs) error {
var ur unix.Reg
ur.X = [30]uint64{
regs.X0, regs.X1, regs.X2, regs.X3, regs.X4, regs.X5, regs.X6,
regs.X7, regs.X8, regs.X9, regs.X10, regs.X11, regs.X12, regs.X13,
regs.X14, regs.X15, regs.X16, regs.X17, regs.X18, regs.X19, regs.X20,
regs.X21, regs.X22, regs.X23, regs.X24, regs.X25, regs.X26, regs.X27,
regs.X28, regs.X29,
}
ur.Lr = regs.X30
ur.Sp = regs.SP
ur.Elr = regs.PC
ur.Spsr = uint32(regs.PSTATE)
return unix.PtraceSetRegs(s.pid, &ur)
}
// FPRegs holds the arm64 FP/NEON register state: the 32 128-bit V
// registers, then FPSR and FPCR (the user_fpsimd shape).
type FPRegs struct {
V [32][16]byte // V0-V31 (128-bit NEON/FP registers)
FPSR uint32
FPCR uint32
}
// GetFPRegs retrieves the FP/NEON register state via PT_GETFPREGS. The
// FreeBSD struct fpreg holds the 32 128-bit V registers followed by FPSR
// and FPCR, the user_fpsimd shape.
func (s *Session) GetFPRegs() (FPRegs, error) {
var fp FPRegs
var fr unix.FpReg
if err := unix.PtraceGetFpRegs(s.pid, &fr); err != nil {
return fp, fmt.Errorf("debug: PT_GETFPREGS: %w", err)
}
for i := range 32 {
copy(fp.V[i][:], fr.Q[i][:])
}
return fp, nil
}
// VectorRegs holds the full SIMD register state.
type VectorRegs struct {
V [32][16]byte // V0-V31 (128-bit)
}
// GetVectorRegs retrieves the SIMD registers.
func (s *Session) GetVectorRegs() (VectorRegs, error) {
var v VectorRegs
fp, err := s.GetFPRegs()
if err != nil {
return v, err
}
copy(v.V[:][:], fp.V[:][:])
return v, nil
}