// Copyright (c) 2026 Petr BalvĂ­n (https://petrbalvin.org) // SPDX-License-Identifier: BSD-3-Clause //go:build freebsd && arm64 package debug // Regs holds the full general-purpose register set of a traced process // (the FreeBSD arm64 struct reg layout, sys/arm64/include/reg.h: x[30], lr, // sp, elr, spsr). type Regs struct { X0 uint64 X1 uint64 X2 uint64 X3 uint64 X4 uint64 X5 uint64 X6 uint64 X7 uint64 X8 uint64 X9 uint64 X10 uint64 X11 uint64 X12 uint64 X13 uint64 X14 uint64 X15 uint64 X16 uint64 X17 uint64 X18 uint64 X19 uint64 X20 uint64 X21 uint64 X22 uint64 X23 uint64 X24 uint64 X25 uint64 X26 uint64 X27 uint64 X28 uint64 X29 uint64 // FP (frame pointer) X30 uint64 // LR (link register) SP uint64 PC uint64 PSTATE uint64 } // GetPC returns the program counter. func (r *Regs) GetPC() uint64 { return r.PC } // SetPC sets the program counter. func (r *Regs) SetPC(pc uint64) { r.PC = pc } // GetSP returns the stack pointer. func (r *Regs) GetSP() uint64 { return r.SP } // RegValue returns the value of the named register, or false if unknown. func (r *Regs) RegValue(name string) (uint64, bool) { switch name { case "x0": return r.X0, true case "x1": return r.X1, true case "x2": return r.X2, true case "x3": return r.X3, true case "x4": return r.X4, true case "x5": return r.X5, true case "x6": return r.X6, true case "x7": return r.X7, true case "x8": return r.X8, true case "x9": return r.X9, true case "x10": return r.X10, true case "x11": return r.X11, true case "x12": return r.X12, true case "x13": return r.X13, true case "x14": return r.X14, true case "x15": return r.X15, true case "x16": return r.X16, true case "x17": return r.X17, true case "x18": return r.X18, true case "x19": return r.X19, true case "x20": return r.X20, true case "x21": return r.X21, true case "x22": return r.X22, true case "x23": return r.X23, true case "x24": return r.X24, true case "x25": return r.X25, true case "x26": return r.X26, true case "x27": return r.X27, true case "x28": return r.X28, true case "x29", "fp": return r.X29, true case "x30", "lr": return r.X30, true case "sp": return r.SP, true case "pc": return r.PC, true default: return 0, false } } // breakpointInsn is the software breakpoint instruction (BRK #0). var breakpointInsn = []byte{0x00, 0x00, 0x20, 0xD4} // BRK #0 // breakpointPCAdjust is how far PC is past the breakpoint instruction after // a trap: 0. The BRK synchronous exception leaves ELR_EL0 on the BRK // itself (ARM DDI 0487), and the FreeBSD EXCP_BRKPT_EL0 handler delivers // the frame's elr unmodified (sys/arm64/arm64/trap.c), so the trap address // is the PC as reported. const breakpointPCAdjust = 0