mirror of https://github.com/x64dbg/TitanEngine
Merge pull request #29 from 3rdit/fix/breakpoint-deletion-race
Fix multi-thread breakpoint deletion race condition
This commit is contained in:
commit
e6570203cc
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
std::vector<BreakPointDetail> BreakPointBuffer;
|
std::vector<BreakPointDetail> BreakPointBuffer;
|
||||||
std::unordered_map<ULONG_PTR, MemoryBreakpointPageDetail> MemoryBreakpointPages;
|
std::unordered_map<ULONG_PTR, MemoryBreakpointPageDetail> MemoryBreakpointPages;
|
||||||
|
std::unordered_set<ULONG_PTR> recentlyDeletedBpx;
|
||||||
|
|
||||||
ULONG_PTR dr7uint(DR7* dr7)
|
ULONG_PTR dr7uint(DR7* dr7)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#include "Global.Engine.Threading.h"
|
#include "Global.Engine.Threading.h"
|
||||||
#include "Global.Engine.h"
|
#include "Global.Engine.h"
|
||||||
|
|
@ -11,6 +12,7 @@
|
||||||
|
|
||||||
extern std::vector<BreakPointDetail> BreakPointBuffer;
|
extern std::vector<BreakPointDetail> BreakPointBuffer;
|
||||||
extern std::unordered_map<ULONG_PTR, MemoryBreakpointPageDetail> MemoryBreakpointPages;
|
extern std::unordered_map<ULONG_PTR, MemoryBreakpointPageDetail> MemoryBreakpointPages;
|
||||||
|
extern std::unordered_set<ULONG_PTR> recentlyDeletedBpx;
|
||||||
|
|
||||||
void uintdr7(ULONG_PTR dr7, DR7* ret);
|
void uintdr7(ULONG_PTR dr7, DR7* ret);
|
||||||
ULONG_PTR dr7uint(DR7* dr7);
|
ULONG_PTR dr7uint(DR7* dr7);
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ void DebuggerReset()
|
||||||
}
|
}
|
||||||
std::vector<BreakPointDetail>().swap(BreakPointBuffer);
|
std::vector<BreakPointDetail>().swap(BreakPointBuffer);
|
||||||
std::unordered_map<ULONG_PTR, MemoryBreakpointPageDetail>().swap(MemoryBreakpointPages);
|
std::unordered_map<ULONG_PTR, MemoryBreakpointPageDetail>().swap(MemoryBreakpointPages);
|
||||||
|
recentlyDeletedBpx.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearProcessList()
|
void ClearProcessList()
|
||||||
|
|
|
||||||
|
|
@ -303,6 +303,7 @@ __declspec(dllexport) bool TITCALL DeleteBPX(ULONG_PTR bpxAddress)
|
||||||
FlushInstructionCache(dbgProcessInformation.hProcess, NULL, 0);
|
FlushInstructionCache(dbgProcessInformation.hProcess, NULL, 0);
|
||||||
VirtualProtectEx(dbgProcessInformation.hProcess, (LPVOID)bpxAddress, BreakPointBuffer.at(found).BreakPointSize, OldProtect, &OldProtect);
|
VirtualProtectEx(dbgProcessInformation.hProcess, (LPVOID)bpxAddress, BreakPointBuffer.at(found).BreakPointSize, OldProtect, &OldProtect);
|
||||||
BreakPointBuffer.erase(BreakPointBuffer.begin() + found);
|
BreakPointBuffer.erase(BreakPointBuffer.begin() + found);
|
||||||
|
recentlyDeletedBpx.insert(bpxAddress);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,8 @@ __declspec(dllexport) void TITCALL DebugLoop()
|
||||||
memset(&DLLDebugFileName, 0, sizeof(DLLDebugFileName));
|
memset(&DLLDebugFileName, 0, sizeof(DLLDebugFileName));
|
||||||
engineFileIsBeingDebugged = true;
|
engineFileIsBeingDebugged = true;
|
||||||
|
|
||||||
|
uint32_t consecutiveTimeouts = 0;
|
||||||
|
|
||||||
while(!BreakDBG) //actual debug loop
|
while(!BreakDBG) //actual debug loop
|
||||||
{
|
{
|
||||||
bool synchronizedStep = false;
|
bool synchronizedStep = false;
|
||||||
|
|
@ -124,10 +126,17 @@ __declspec(dllexport) void TITCALL DebugLoop()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Regular timeout, wait again
|
// Regular timeout, wait again
|
||||||
|
// After 2 consecutive timeouts, clear recently deleted breakpoints
|
||||||
|
consecutiveTimeouts++;
|
||||||
|
if(consecutiveTimeouts >= 2)
|
||||||
|
recentlyDeletedBpx.clear();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Event received, reset timeout counter
|
||||||
|
consecutiveTimeouts = 0;
|
||||||
|
|
||||||
if(IsDbgReplyLaterSupported)
|
if(IsDbgReplyLaterSupported)
|
||||||
{
|
{
|
||||||
if(DBGEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT)
|
if(DBGEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT)
|
||||||
|
|
@ -589,11 +598,36 @@ __declspec(dllexport) void TITCALL DebugLoop()
|
||||||
{
|
{
|
||||||
if(DebugAttachedToProcess || !FirstBPX) //program generated a breakpoint exception
|
if(DebugAttachedToProcess || !FirstBPX) //program generated a breakpoint exception
|
||||||
{
|
{
|
||||||
DBGCode = DBG_EXCEPTION_NOT_HANDLED;
|
ULONG_PTR exceptionAddress = (ULONG_PTR)DBGEvent.u.Exception.ExceptionRecord.ExceptionAddress;
|
||||||
if(DBGCustomHandler->chBreakPoint != NULL)
|
|
||||||
|
if(recentlyDeletedBpx.find(exceptionAddress) != recentlyDeletedBpx.end())
|
||||||
{
|
{
|
||||||
myCustomHandler = (fCustomHandler)((LPVOID)DBGCustomHandler->chBreakPoint);
|
//breakpoint was recently deleted - handle the stale event gracefully
|
||||||
myCustomHandler(&DBGEvent.u.Exception.ExceptionRecord);
|
hActiveThread = EngineOpenThread(THREAD_GETSETSUSPEND, false, DBGEvent.dwThreadId);
|
||||||
|
if(hActiveThread != NULL)
|
||||||
|
{
|
||||||
|
CONTEXT myDBGContext;
|
||||||
|
myDBGContext.ContextFlags = ContextControlFlags;
|
||||||
|
GetThreadContext(hActiveThread, &myDBGContext);
|
||||||
|
#if defined(_WIN64)
|
||||||
|
myDBGContext.Rip = exceptionAddress;
|
||||||
|
#else
|
||||||
|
myDBGContext.Eip = (DWORD)exceptionAddress;
|
||||||
|
#endif
|
||||||
|
SetThreadContext(hActiveThread, &myDBGContext);
|
||||||
|
EngineCloseHandle(hActiveThread);
|
||||||
|
DBGCode = DBG_CONTINUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//not a recently deleted breakpoint - pass to debuggee
|
||||||
|
DBGCode = DBG_EXCEPTION_NOT_HANDLED;
|
||||||
|
if(DBGCustomHandler->chBreakPoint != NULL)
|
||||||
|
{
|
||||||
|
myCustomHandler = (fCustomHandler)((LPVOID)DBGCustomHandler->chBreakPoint);
|
||||||
|
myCustomHandler(&DBGEvent.u.Exception.ExceptionRecord);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else //system breakpoint
|
else //system breakpoint
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue