// Copyright (c) 2026 Petr BalvĂ­n (https://petrbalvin.org) // SPDX-License-Identifier: BSD-3-Clause //go:build freebsd && arm64 package debug import ( "encoding/binary" "fmt" ) func printRegs(regs *Regs, codeBase, funcOff uint64) { fmt.Printf(" PC = %#016x (func+%#x)\n", regs.PC, regs.PC-codeBase-funcOff) fmt.Printf(" SP = %#016x FP = %#016x\n", regs.SP, regs.X29) fmt.Printf(" LR = %#016x\n", regs.X30) fmt.Printf(" X0 = %#016x X1 = %#016x\n", regs.X0, regs.X1) fmt.Printf(" X2 = %#016x X3 = %#016x\n", regs.X2, regs.X3) fmt.Printf(" X4 = %#016x X5 = %#016x\n", regs.X4, regs.X5) fmt.Printf(" X6 = %#016x X7 = %#016x\n", regs.X6, regs.X7) fmt.Printf(" X8 = %#016x X9 = %#016x\n", regs.X8, regs.X9) fmt.Printf(" X10 = %#016x X11 = %#016x\n", regs.X10, regs.X11) fmt.Printf(" X12 = %#016x X13 = %#016x\n", regs.X12, regs.X13) fmt.Printf(" X14 = %#016x X15 = %#016x\n", regs.X14, regs.X15) fmt.Printf(" X16 = %#016x X17 = %#016x\n", regs.X16, regs.X17) fmt.Printf(" X18 = %#016x X19 = %#016x\n", regs.X18, regs.X19) fmt.Printf(" X20 = %#016x X21 = %#016x\n", regs.X20, regs.X21) fmt.Printf(" X22 = %#016x X23 = %#016x\n", regs.X22, regs.X23) fmt.Printf(" X24 = %#016x X25 = %#016x\n", regs.X24, regs.X25) fmt.Printf(" X26 = %#016x X27 = %#016x\n", regs.X26, regs.X27) fmt.Printf(" X28 = %#016x PSTATE = %#x\n", regs.X28, regs.PSTATE) } func printVectorRegs(v *VectorRegs) { fmt.Println("\n Vector registers (V0-V31):") for i := 0; i < 32; i += 2 { fmt.Printf(" V%-2d = %016x%016x\n", i, binary.LittleEndian.Uint64(v.V[i][8:16]), binary.LittleEndian.Uint64(v.V[i][0:8])) fmt.Printf(" V%-2d = %016x%016x\n", i+1, binary.LittleEndian.Uint64(v.V[i+1][8:16]), binary.LittleEndian.Uint64(v.V[i+1][0:8])) } } // SetReg modifies a register value in the debuggee. func (s *Session) SetReg(name string, value uint64) error { regs, err := s.GetRegs() if err != nil { return err } switch name { case "x0": regs.X0 = value case "x1": regs.X1 = value case "x2": regs.X2 = value case "x3": regs.X3 = value case "x4": regs.X4 = value case "x5": regs.X5 = value case "x6": regs.X6 = value case "x7": regs.X7 = value case "x8": regs.X8 = value case "x9": regs.X9 = value case "x10": regs.X10 = value case "x11": regs.X11 = value case "x12": regs.X12 = value case "x13": regs.X13 = value case "x14": regs.X14 = value case "x15": regs.X15 = value case "x16": regs.X16 = value case "x17": regs.X17 = value case "x18": regs.X18 = value case "x19": regs.X19 = value case "x20": regs.X20 = value case "x21": regs.X21 = value case "x22": regs.X22 = value case "x23": regs.X23 = value case "x24": regs.X24 = value case "x25": regs.X25 = value case "x26": regs.X26 = value case "x27": regs.X27 = value case "x28": regs.X28 = value case "x29", "fp": regs.X29 = value case "x30", "lr": regs.X30 = value case "sp": regs.SP = value case "pc": regs.PC = value default: return fmt.Errorf("debug: unknown register %q", name) } return s.SetRegs(®s) } // archReturnAddr reads the return address from LR (arm64 convention). func archReturnAddr(s *Session, regs *Regs) (uint64, error) { return regs.X30, nil } // archSPLabel returns the SP register name for display. func archSPLabel() string { return "SP" }