Test / vet (push) Successful in 44s
Release / build (amd64, linux) (push) Successful in 39s
Release / build (arm64, linux) (push) Successful in 38s
Release / build (loong64, linux) (push) Successful in 39s
Release / build (riscv64, linux) (push) Successful in 39s
Test / test (push) Successful in 1m58s
Release / release (push) Successful in 18s
Test / build (push) Successful in 37s
Assisted-by: DeepSeek V4 Pro
91 lines
1.9 KiB
Go
91 lines
1.9 KiB
Go
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (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 }
|