From 1533cc3e84a4244ef06929a798be5dff15c4a227 Mon Sep 17 00:00:00 2001 From: AzuLX Date: Fri, 9 Jan 2026 19:08:26 +0000 Subject: [PATCH] track deleted breakpoints to handle stale events safely --- GleeBug/Debugger.Loop.Exception.cpp | 11 ++++------- GleeBug/Debugger.Loop.cpp | 11 ++++++++++- GleeBug/Debugger.Process.Breakpoint.cpp | 2 ++ GleeBug/Debugger.Process.h | 2 ++ 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/GleeBug/Debugger.Loop.Exception.cpp b/GleeBug/Debugger.Loop.Exception.cpp index 411455c..00fe270 100644 --- a/GleeBug/Debugger.Loop.Exception.cpp +++ b/GleeBug/Debugger.Loop.Exception.cpp @@ -21,17 +21,14 @@ namespace GleeBug } else { - //check if this was a deleted breakpoint - //if the byte at the exception address is not 0xCC, our breakpoint was deleted - //and we should set IP back and continue execution - uint8 currentByte = 0xCC; - if(mThread && mProcess->MemReadUnsafe(exceptionAddress, ¤tByte, 1) && currentByte != 0xCC) + //check if this address had a breakpoint that was recently deleted + auto& deletedBps = mProcess->recentlyDeletedSwbp; + auto foundIt = std::find(deletedBps.begin(), deletedBps.end(), exceptionAddress); + if(foundIt != deletedBps.end() && mThread) { - //this was our deleted breakpoint, set IP back and continue Registers(mThread->hThread, CONTEXT_CONTROL).Gip = exceptionAddress; mContinueStatus = DBG_CONTINUE; } - //else: byte is 0xCC, this is a real int3 in original code, let debuggee handle it } return; } diff --git a/GleeBug/Debugger.Loop.cpp b/GleeBug/Debugger.Loop.cpp index 6f54e69..954da2e 100644 --- a/GleeBug/Debugger.Loop.cpp +++ b/GleeBug/Debugger.Loop.cpp @@ -40,6 +40,8 @@ namespace GleeBug IsDbgReplyLaterSupported = mSafeStep; } + uint32 consecutiveTimeouts = 0; + while(!mBreakDebugger) { //wait for a debug event @@ -65,11 +67,18 @@ namespace GleeBug #endif else { - // Regular timeout, wait again + //after 2 consecutive timeouts, clear recently deleted breakpoints + //any stale events would have been delivered by now + consecutiveTimeouts++; + if(consecutiveTimeouts >= 2 && mProcess) + mProcess->recentlyDeletedSwbp.clear(); continue; } } + //event received, reset timeout counter + consecutiveTimeouts = 0; + // Handle safe stepping if(IsDbgReplyLaterSupported) { diff --git a/GleeBug/Debugger.Process.Breakpoint.cpp b/GleeBug/Debugger.Process.Breakpoint.cpp index 65e046b..e67d35a 100644 --- a/GleeBug/Debugger.Process.Breakpoint.cpp +++ b/GleeBug/Debugger.Process.Breakpoint.cpp @@ -68,6 +68,8 @@ namespace GleeBug return false; FlushInstructionCache(hProcess, nullptr, 0); + recentlyDeletedSwbp.push_back(address); + //remove the breakpoint from the maps softwareBreakpointReferences.erase(info.address); breakpoints.erase(found); diff --git a/GleeBug/Debugger.Process.h b/GleeBug/Debugger.Process.h index fd604f1..3459fcf 100644 --- a/GleeBug/Debugger.Process.h +++ b/GleeBug/Debugger.Process.h @@ -32,6 +32,8 @@ namespace GleeBug MemoryBreakpointSet memoryBreakpointRanges; MemoryBreakpointMap memoryBreakpointPages; + std::vector recentlyDeletedSwbp; + /** \brief Constructor. \param hProcess Process handle.