fix(debug): handle mapping edges, stray traps and dying debuggees
Assisted-by: GLM 5.3
This commit is contained in:
@@ -75,17 +75,27 @@ func (s *Session) setDbRegs(dr *dbreg) error {
|
||||
// archStopTrace classifies a TRAP_TRACE stop. On amd64 the kernel
|
||||
// delivers both the completed single-step and the debug-register hit
|
||||
// through T_TRCTRAP with TRAP_TRACE (sys/amd64/amd64/trap.c), and DR6's
|
||||
// B0-B3 bits name the watchpoint that fired.
|
||||
// B0-B3 bits name the watchpoint that fired. The bits are sticky ("the
|
||||
// processor never clears DR6", Intel SDM vol 3, "Debug Registers"), so
|
||||
// they are acknowledged here: cleared once read, or the next hit on a
|
||||
// different slot would still see this slot's bit set and report this
|
||||
// slot's address again.
|
||||
func archStopTrace(s *Session, siAddr uint64) (StopReason, uint64) {
|
||||
dr, err := s.getDbRegs()
|
||||
if err != nil {
|
||||
return StopSingleStep, 0
|
||||
}
|
||||
if status := dr.Dr[drStatus]; status&0xF != 0 {
|
||||
for slot := range 4 {
|
||||
if status&(1<<slot) != 0 && dr.Dr[slot] != 0 {
|
||||
return StopWatchpoint, dr.Dr[slot]
|
||||
}
|
||||
status := dr.Dr[drStatus] & 0xF
|
||||
if status == 0 {
|
||||
return StopSingleStep, 0
|
||||
}
|
||||
// Best effort: the write-back only fails for a dead debuggee, for
|
||||
// which no further watchpoint can fire anyway.
|
||||
dr.Dr[drStatus] &^= 0xF
|
||||
_ = s.setDbRegs(dr)
|
||||
for slot := range 4 {
|
||||
if status&(1<<slot) != 0 && dr.Dr[slot] != 0 {
|
||||
return StopWatchpoint, dr.Dr[slot]
|
||||
}
|
||||
}
|
||||
return StopSingleStep, 0
|
||||
|
||||
Reference in New Issue
Block a user