// Copyright (c) 2026 Petr BalvĂ­n (https://petrbalvin.org) // SPDX-License-Identifier: BSD-3-Clause package debug // Regs holds the full general-purpose register set of a traced process // (the Linux amd64 user_regs_struct layout). type Regs struct { R15 uint64 R14 uint64 R13 uint64 R12 uint64 RBP uint64 RBX uint64 R11 uint64 R10 uint64 R9 uint64 R8 uint64 RAX uint64 RCX uint64 RDX uint64 RSI uint64 RDI uint64 OrigRAX uint64 RIP uint64 CS uint64 RFLAGS uint64 RSP uint64 SS uint64 FSBase uint64 GSBase uint64 DS uint64 ES uint64 FS uint64 GS uint64 } // tracer abstracts the minimal ptrace operations needed by the breakpoint // manager and the stop-information helpers. The live implementation is // *Session (ptrace_linux_amd64.go); tests supply a mock. type tracer interface { Peek(addr uint64) (uint64, error) Poke(addr uint64, val uint64) error SetRegs(regs *Regs) error Pid() int } // mockTracer records Peek/Poke calls and provides fake register state. type mockTracer struct { mem map[uint64]byte peeks []uint64 pokes []struct { addr uint64 val uint64 } regs *Regs } func newMockTracer() *mockTracer { return &mockTracer{ mem: make(map[uint64]byte), regs: &Regs{}, } } func (m *mockTracer) Peek(addr uint64) (uint64, error) { m.peeks = append(m.peeks, addr) var val uint64 for i := uint64(0); i < 8; i++ { val |= uint64(m.mem[addr+i]) << (i * 8) } return val, nil } func (m *mockTracer) Poke(addr uint64, val uint64) error { m.pokes = append(m.pokes, struct { addr uint64 val uint64 }{addr, val}) for i := uint64(0); i < 8; i++ { m.mem[addr+i] = byte(val >> (i * 8)) } return nil } func (m *mockTracer) SetRegs(regs *Regs) error { m.regs = regs return nil } func (m *mockTracer) Pid() int { return 42 }