refactor(debug): make Regs and breakpoint arch-neutral for arm64
Assisted-by: MiMo V2.5 Pro
This commit is contained in:
+29
-47
@@ -25,43 +25,8 @@ type Condition struct {
|
||||
|
||||
// Eval checks the condition against the current registers.
|
||||
func (c *Condition) Eval(regs *Regs) bool {
|
||||
var actual uint64
|
||||
switch c.Reg {
|
||||
case "rax", "eax", "ax", "al":
|
||||
actual = regs.RAX
|
||||
case "rbx", "ebx", "bx", "bl":
|
||||
actual = regs.RBX
|
||||
case "rcx", "ecx", "cx", "cl":
|
||||
actual = regs.RCX
|
||||
case "rdx", "edx", "dx", "dl":
|
||||
actual = regs.RDX
|
||||
case "rsi", "esi", "si":
|
||||
actual = regs.RSI
|
||||
case "rdi", "edi", "di":
|
||||
actual = regs.RDI
|
||||
case "rbp", "ebp", "bp":
|
||||
actual = regs.RBP
|
||||
case "rsp", "esp", "sp":
|
||||
actual = regs.RSP
|
||||
case "r8":
|
||||
actual = regs.R8
|
||||
case "r9":
|
||||
actual = regs.R9
|
||||
case "r10":
|
||||
actual = regs.R10
|
||||
case "r11":
|
||||
actual = regs.R11
|
||||
case "r12":
|
||||
actual = regs.R12
|
||||
case "r13":
|
||||
actual = regs.R13
|
||||
case "r14":
|
||||
actual = regs.R14
|
||||
case "r15":
|
||||
actual = regs.R15
|
||||
case "rip", "eip":
|
||||
actual = regs.RIP
|
||||
default:
|
||||
actual, ok := regs.RegValue(c.Reg)
|
||||
if !ok {
|
||||
return true // unknown register — don't block
|
||||
}
|
||||
switch c.Op {
|
||||
@@ -106,14 +71,18 @@ func (bm *Breakpoints) SetWithCond(addr uint64, label string, cond *Condition) (
|
||||
bp.Cond = cond
|
||||
return bp, nil
|
||||
}
|
||||
// Read the original byte.
|
||||
// Read the original bytes.
|
||||
word, err := bm.t.Peek(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
orig := byte(word)
|
||||
// Patch with INT3 (0xCC), preserving the rest of the word.
|
||||
patched := (word &^ 0xFF) | 0xCC
|
||||
// Patch with the breakpoint instruction, preserving the rest of the word.
|
||||
mask := uint64(0)
|
||||
for range breakpointInsn {
|
||||
mask = (mask << 8) | 0xFF
|
||||
}
|
||||
patched := (word &^ mask) | breakpointWord(breakpointInsn)
|
||||
if err := bm.t.Poke(addr, patched); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -196,12 +165,12 @@ func (bm *Breakpoints) All() []*Breakpoint {
|
||||
}
|
||||
|
||||
// HandleTrap is called after the debuggee stops on SIGTRAP. It checks
|
||||
// whether the trap was caused by one of our breakpoints (RIP-1 matches
|
||||
// a breakpoint address), restores the original byte, rewinds RIP, and
|
||||
// whether the trap was caused by one of our breakpoints (PC-adjust matches
|
||||
// a breakpoint address), restores the original byte, rewinds PC, and
|
||||
// returns the breakpoint that was hit (or nil if it was a single-step).
|
||||
func (bm *Breakpoints) HandleTrap(regs *Regs) *Breakpoint {
|
||||
// After INT3, RIP points to the byte AFTER the 0xCC.
|
||||
trapAddr := regs.RIP - 1
|
||||
// After a breakpoint trap, PC points past the breakpoint instruction.
|
||||
trapAddr := regs.GetPC() - uint64(breakpointPCAdjust)
|
||||
bp, ok := bm.bps[trapAddr]
|
||||
if !ok || !bp.Enabled {
|
||||
return nil // single-step trap or unknown
|
||||
@@ -225,8 +194,8 @@ func (bm *Breakpoints) HandleTrap(regs *Regs) *Breakpoint {
|
||||
restored := (word &^ 0xFF) | uint64(bp.Orig)
|
||||
bm.t.Poke(trapAddr, restored)
|
||||
}
|
||||
// Rewind RIP to re-execute the original instruction.
|
||||
regs.RIP = trapAddr
|
||||
// Rewind PC to re-execute the original instruction.
|
||||
regs.SetPC(trapAddr)
|
||||
bm.t.SetRegs(regs)
|
||||
return bp
|
||||
}
|
||||
@@ -243,6 +212,19 @@ func (bm *Breakpoints) Reinsert(addr uint64) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
patched := (word &^ 0xFF) | 0xCC
|
||||
mask := uint64(0)
|
||||
for range breakpointInsn {
|
||||
mask = (mask << 8) | 0xFF
|
||||
}
|
||||
patched := (word &^ mask) | breakpointWord(breakpointInsn)
|
||||
return bm.t.Poke(addr, patched)
|
||||
}
|
||||
|
||||
// breakpointWord converts the breakpoint instruction bytes to a uint64.
|
||||
func breakpointWord(insn []byte) uint64 {
|
||||
var w uint64
|
||||
for i, b := range insn {
|
||||
w |= uint64(b) << (i * 8)
|
||||
}
|
||||
return w
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user