// Copyright (c) 2026 Petr BalvĂ­n (https://petrbalvin.org) // SPDX-License-Identifier: BSD-3-Clause //go:build linux && amd64 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 } // GetPC returns the program counter. func (r *Regs) GetPC() uint64 { return r.RIP } // SetPC sets the program counter. func (r *Regs) SetPC(pc uint64) { r.RIP = pc } // GetSP returns the stack pointer. func (r *Regs) GetSP() uint64 { return r.RSP } // RegValue returns the value of the named register, or false if unknown. func (r *Regs) RegValue(name string) (uint64, bool) { switch name { case "rax", "eax", "ax", "al": return r.RAX, true case "rbx", "ebx", "bx", "bl": return r.RBX, true case "rcx", "ecx", "cx", "cl": return r.RCX, true case "rdx", "edx", "dx", "dl": return r.RDX, true case "rsi", "esi", "si": return r.RSI, true case "rdi", "edi", "di": return r.RDI, true case "rbp", "ebp", "bp": return r.RBP, true case "rsp", "esp", "sp": return r.RSP, true case "r8": return r.R8, true case "r9": return r.R9, true case "r10": return r.R10, true case "r11": return r.R11, true case "r12": return r.R12, true case "r13": return r.R13, true case "r14": return r.R14, true case "r15": return r.R15, true case "rip", "eip": return r.RIP, true default: return 0, false } } // breakpointInsn is the software breakpoint instruction. var breakpointInsn = []byte{0xCC} // INT3 // breakpointPCAdjust is how far PC is past the breakpoint instruction after a trap. const breakpointPCAdjust = 1