DBG: implement DLL breakpoints directly in x64dbg
This commit is contained in:
parent
a514176750
commit
0762182973
|
@ -898,7 +898,7 @@ static bool cbDeleteAllDllBreakpoints(const BREAKPOINT* bp)
|
||||||
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not delete DLL breakpoint %s (BpDelete)\n"), bp->mod);
|
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not delete DLL breakpoint %s (BpDelete)\n"), bp->mod);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(!LibrarianRemoveBreakPoint(bp->mod, bp->titantype))
|
if(!dbgdeletedllbreakpoint(bp->mod, bp->titantype))
|
||||||
{
|
{
|
||||||
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not delete DLL breakpoint %s (LibrarianRemoveBreakPoint)\n"), bp->mod);
|
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not delete DLL breakpoint %s (LibrarianRemoveBreakPoint)\n"), bp->mod);
|
||||||
return false;
|
return false;
|
||||||
|
@ -916,7 +916,7 @@ static bool cbEnableAllDllBreakpoints(const BREAKPOINT* bp)
|
||||||
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (BpEnable)\n"), bp->mod);
|
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (BpEnable)\n"), bp->mod);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(!LibrarianSetBreakPoint(bp->mod, bp->titantype, bp->singleshoot, (void*)cbLibrarianBreakpoint))
|
if(!dbgsetdllbreakpoint(bp->mod, bp->titantype, bp->singleshoot))
|
||||||
{
|
{
|
||||||
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (LibrarianSetBreakPoint)\n"), bp->mod);
|
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (LibrarianSetBreakPoint)\n"), bp->mod);
|
||||||
return false;
|
return false;
|
||||||
|
@ -934,7 +934,7 @@ static bool cbDisableAllDllBreakpoints(const BREAKPOINT* bp)
|
||||||
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable DLL breakpoint %s (BpEnable)\n"), bp->mod);
|
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable DLL breakpoint %s (BpEnable)\n"), bp->mod);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(!LibrarianRemoveBreakPoint(bp->mod, bp->titantype))
|
if(!dbgdeletedllbreakpoint(bp->mod, bp->titantype))
|
||||||
{
|
{
|
||||||
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable DLL breakpoint %s (LibrarianRemoveBreakPoint)\n"), bp->mod);
|
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable DLL breakpoint %s (LibrarianRemoveBreakPoint)\n"), bp->mod);
|
||||||
return false;
|
return false;
|
||||||
|
@ -946,6 +946,7 @@ bool cbDebugBpDll(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
if(IsArgumentsLessThan(argc, 2))
|
if(IsArgumentsLessThan(argc, 2))
|
||||||
return false;
|
return false;
|
||||||
|
_strlwr_s(argv[1], strlen(argv[1]) + 1); //NOTE: does not really work on unicode strings
|
||||||
DWORD type = UE_ON_LIB_ALL;
|
DWORD type = UE_ON_LIB_ALL;
|
||||||
if(argc > 2)
|
if(argc > 2)
|
||||||
{
|
{
|
||||||
|
@ -967,7 +968,7 @@ bool cbDebugBpDll(int argc, char* argv[])
|
||||||
dputs(QT_TRANSLATE_NOOP("DBG", "Error creating Dll breakpoint! (BpNewDll)"));
|
dputs(QT_TRANSLATE_NOOP("DBG", "Error creating Dll breakpoint! (BpNewDll)"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(!LibrarianSetBreakPoint(argv[1], type, singleshoot, (void*)cbLibrarianBreakpoint))
|
if(!dbgsetdllbreakpoint(argv[1], type, singleshoot))
|
||||||
{
|
{
|
||||||
dputs(QT_TRANSLATE_NOOP("DBG", "Error creating Dll breakpoint! (LibrarianSetBreakPoint)"));
|
dputs(QT_TRANSLATE_NOOP("DBG", "Error creating Dll breakpoint! (LibrarianSetBreakPoint)"));
|
||||||
return false;
|
return false;
|
||||||
|
@ -993,6 +994,7 @@ bool cbDebugBcDll(int argc, char* argv[])
|
||||||
DebugUpdateBreakpointsViewAsync();
|
DebugUpdateBreakpointsViewAsync();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
_strlwr_s(argv[1], strlen(argv[1]) + 1); //NOTE: does not really work on unicode strings
|
||||||
BREAKPOINT bp;
|
BREAKPOINT bp;
|
||||||
if(!BpGetAny(BPDLL, argv[1], &bp))
|
if(!BpGetAny(BPDLL, argv[1], &bp))
|
||||||
return false;
|
return false;
|
||||||
|
@ -1001,7 +1003,7 @@ bool cbDebugBcDll(int argc, char* argv[])
|
||||||
dputs(QT_TRANSLATE_NOOP("DBG", "Failed to remove DLL breakpoint..."));
|
dputs(QT_TRANSLATE_NOOP("DBG", "Failed to remove DLL breakpoint..."));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(!LibrarianRemoveBreakPoint(bp.mod, bp.titantype))
|
if(!dbgdeletedllbreakpoint(bp.mod, bp.titantype))
|
||||||
{
|
{
|
||||||
dputs(QT_TRANSLATE_NOOP("DBG", "Failed to remove DLL breakpoint..."));
|
dputs(QT_TRANSLATE_NOOP("DBG", "Failed to remove DLL breakpoint..."));
|
||||||
return false;
|
return false;
|
||||||
|
@ -1026,6 +1028,7 @@ bool cbDebugBpDllEnable(int argc, char* argv[])
|
||||||
GuiUpdateAllViews();
|
GuiUpdateAllViews();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
_strlwr_s(argv[1], strlen(argv[1]) + 1); //NOTE: does not really work on unicode strings
|
||||||
BREAKPOINT found;
|
BREAKPOINT found;
|
||||||
duint addr = 0;
|
duint addr = 0;
|
||||||
if(!BpGetAny(BPDLL, argv[1], &found)) //invalid DLL breakpoint
|
if(!BpGetAny(BPDLL, argv[1], &found)) //invalid DLL breakpoint
|
||||||
|
@ -1043,7 +1046,7 @@ bool cbDebugBpDllEnable(int argc, char* argv[])
|
||||||
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (BpEnable)\n"), found.mod);
|
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (BpEnable)\n"), found.mod);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(!LibrarianSetBreakPoint(found.mod, found.titantype, found.singleshoot, (void*)cbLibrarianBreakpoint))
|
if(!dbgsetdllbreakpoint(found.mod, found.titantype, found.singleshoot))
|
||||||
{
|
{
|
||||||
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (LibrarianSetBreakPoint)\n"), found.mod);
|
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not enable DLL breakpoint %s (LibrarianSetBreakPoint)\n"), found.mod);
|
||||||
}
|
}
|
||||||
|
@ -1067,6 +1070,7 @@ bool cbDebugBpDllDisable(int argc, char* argv[])
|
||||||
GuiUpdateAllViews();
|
GuiUpdateAllViews();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
_strlwr_s(argv[1], strlen(argv[1]) + 1); //NOTE: does not really work on unicode strings
|
||||||
BREAKPOINT found;
|
BREAKPOINT found;
|
||||||
duint addr = 0;
|
duint addr = 0;
|
||||||
if(!BpGetAny(BPDLL, argv[1], &found)) //invalid DLL breakpoint
|
if(!BpGetAny(BPDLL, argv[1], &found)) //invalid DLL breakpoint
|
||||||
|
@ -1084,7 +1088,7 @@ bool cbDebugBpDllDisable(int argc, char* argv[])
|
||||||
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable DLL breakpoint %s (BpEnable)\n"), found.mod);
|
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable DLL breakpoint %s (BpEnable)\n"), found.mod);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(!LibrarianRemoveBreakPoint(found.mod, found.titantype))
|
if(!dbgdeletedllbreakpoint(found.mod, found.titantype))
|
||||||
{
|
{
|
||||||
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable DLL breakpoint %s (LibrarianRemoveBreakPoint)\n"), found.mod);
|
dprintf(QT_TRANSLATE_NOOP("DBG", "Could not disable DLL breakpoint %s (LibrarianRemoveBreakPoint)\n"), found.mod);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,6 @@ static bool isDetachedByUser = false;
|
||||||
static bool bIsAttached = false;
|
static bool bIsAttached = false;
|
||||||
static bool bSkipExceptions = false;
|
static bool bSkipExceptions = false;
|
||||||
static duint skipExceptionCount = 0;
|
static duint skipExceptionCount = 0;
|
||||||
static bool bBreakOnNextDll = false;
|
|
||||||
static bool bFreezeStack = false;
|
static bool bFreezeStack = false;
|
||||||
static std::vector<ExceptionRange> ignoredExceptionRange;
|
static std::vector<ExceptionRange> ignoredExceptionRange;
|
||||||
static HANDLE hEvent = 0;
|
static HANDLE hEvent = 0;
|
||||||
|
@ -386,6 +385,39 @@ void dbgtracebrowserneedsupdate()
|
||||||
bTraceBrowserNeedsUpdate = true;
|
bTraceBrowserNeedsUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::unordered_map<std::string, std::pair<DWORD, bool>> dllBreakpoints;
|
||||||
|
|
||||||
|
bool dbgsetdllbreakpoint(const char* mod, DWORD type, bool singleshoot)
|
||||||
|
{
|
||||||
|
EXCLUSIVE_ACQUIRE(LockDllBreakpoints);
|
||||||
|
return dllBreakpoints.insert({ mod, { type, singleshoot } }).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dbgdeletedllbreakpoint(const char* mod, DWORD type)
|
||||||
|
{
|
||||||
|
EXCLUSIVE_ACQUIRE(LockDllBreakpoints);
|
||||||
|
auto found = dllBreakpoints.find(mod);
|
||||||
|
if(found == dllBreakpoints.end())
|
||||||
|
return false;
|
||||||
|
dllBreakpoints.erase(found);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dbghandledllbreakpoint(const char* mod, bool loadDll)
|
||||||
|
{
|
||||||
|
EXCLUSIVE_ACQUIRE(LockDllBreakpoints);
|
||||||
|
auto shouldBreak = false;
|
||||||
|
auto found = dllBreakpoints.find(mod);
|
||||||
|
if(found != dllBreakpoints.end())
|
||||||
|
{
|
||||||
|
if(found->second.first == UE_ON_LIB_ALL || found->second.first == (loadDll ? UE_ON_LIB_LOAD : UE_ON_LIB_UNLOAD))
|
||||||
|
shouldBreak = true;
|
||||||
|
if(found->second.second)
|
||||||
|
dllBreakpoints.erase(found);
|
||||||
|
}
|
||||||
|
return shouldBreak;
|
||||||
|
}
|
||||||
|
|
||||||
static DWORD WINAPI updateCallStackThread(duint ptr)
|
static DWORD WINAPI updateCallStackThread(duint ptr)
|
||||||
{
|
{
|
||||||
stackupdatecallstack(ptr);
|
stackupdatecallstack(ptr);
|
||||||
|
@ -920,11 +952,6 @@ void cbRunToUserCodeBreakpoint(void* ExceptionAddress)
|
||||||
wait(WAITID_RUN);
|
wait(WAITID_RUN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cbLibrarianBreakpoint(void* lpData)
|
|
||||||
{
|
|
||||||
bBreakOnNextDll = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL CALLBACK SymRegisterCallbackProc64(HANDLE, ULONG ActionCode, ULONG64 CallbackData, ULONG64)
|
static BOOL CALLBACK SymRegisterCallbackProc64(HANDLE, ULONG ActionCode, ULONG64 CallbackData, ULONG64)
|
||||||
{
|
{
|
||||||
PIMAGEHLP_CBA_EVENT evt;
|
PIMAGEHLP_CBA_EVENT evt;
|
||||||
|
@ -1060,8 +1087,7 @@ bool cbSetDLLBreakpoints(const BREAKPOINT* bp)
|
||||||
return true;
|
return true;
|
||||||
if(bp->type != BPDLL)
|
if(bp->type != BPDLL)
|
||||||
return true;
|
return true;
|
||||||
dputs("debug:dll breakpoint in database\n");
|
dbgsetdllbreakpoint(bp->mod, bp->titantype, bp->singleshoot);
|
||||||
LibrarianSetBreakPoint(bp->mod, bp->titantype, bp->singleshoot, (void*)cbLibrarianBreakpoint);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1674,7 +1700,9 @@ static void cbLoadDll(LOAD_DLL_DEBUG_INFO* LoadDll)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((bBreakOnNextDll || settingboolget("Events", "DllEntry")) && !bAlreadySetEntry)
|
auto breakOnDll = dbghandledllbreakpoint(modname, true);
|
||||||
|
|
||||||
|
if((breakOnDll || settingboolget("Events", "DllEntry")) && !bAlreadySetEntry)
|
||||||
{
|
{
|
||||||
auto entry = ModEntryFromAddr(duint(base));
|
auto entry = ModEntryFromAddr(duint(base));
|
||||||
if(entry)
|
if(entry)
|
||||||
|
@ -1722,9 +1750,8 @@ static void cbLoadDll(LOAD_DLL_DEBUG_INFO* LoadDll)
|
||||||
callbackInfo.modname = modname;
|
callbackInfo.modname = modname;
|
||||||
plugincbcall(CB_LOADDLL, &callbackInfo);
|
plugincbcall(CB_LOADDLL, &callbackInfo);
|
||||||
|
|
||||||
if(bBreakOnNextDll)
|
if(breakOnDll)
|
||||||
{
|
{
|
||||||
bBreakOnNextDll = false;
|
|
||||||
cbGenericBreakpoint(BPDLL, DLLDebugFileName);
|
cbGenericBreakpoint(BPDLL, DLLDebugFileName);
|
||||||
}
|
}
|
||||||
else if(settingboolget("Events", "DllLoad"))
|
else if(settingboolget("Events", "DllLoad"))
|
||||||
|
@ -1756,9 +1783,8 @@ static void cbUnloadDll(UNLOAD_DLL_DEBUG_INFO* UnloadDll)
|
||||||
SafeSymUnloadModule64(fdProcessInfo->hProcess, (DWORD64)base);
|
SafeSymUnloadModule64(fdProcessInfo->hProcess, (DWORD64)base);
|
||||||
dprintf(QT_TRANSLATE_NOOP("DBG", "DLL Unloaded: %p %s\n"), base, modname);
|
dprintf(QT_TRANSLATE_NOOP("DBG", "DLL Unloaded: %p %s\n"), base, modname);
|
||||||
|
|
||||||
if(bBreakOnNextDll)
|
if(dbghandledllbreakpoint(modname, false))
|
||||||
{
|
{
|
||||||
bBreakOnNextDll = false;
|
|
||||||
cbGenericBreakpoint(BPDLL, modname);
|
cbGenericBreakpoint(BPDLL, modname);
|
||||||
}
|
}
|
||||||
else if(settingboolget("Events", "DllUnload"))
|
else if(settingboolget("Events", "DllUnload"))
|
||||||
|
@ -2534,7 +2560,6 @@ static void debugLoopFunction(void* lpParameter, bool attach)
|
||||||
//initialize variables
|
//initialize variables
|
||||||
bIsAttached = attach;
|
bIsAttached = attach;
|
||||||
dbgsetskipexceptions(false);
|
dbgsetskipexceptions(false);
|
||||||
bBreakOnNextDll = false;
|
|
||||||
bFreezeStack = false;
|
bFreezeStack = false;
|
||||||
|
|
||||||
//prepare attach/createprocess
|
//prepare attach/createprocess
|
||||||
|
@ -2711,12 +2736,10 @@ static void debugLoopFunction(void* lpParameter, bool attach)
|
||||||
|
|
||||||
//message the user/do final stuff
|
//message the user/do final stuff
|
||||||
RemoveAllBreakPoints(UE_OPTION_REMOVEALL); //remove all breakpoints
|
RemoveAllBreakPoints(UE_OPTION_REMOVEALL); //remove all breakpoints
|
||||||
BpEnumAll([](const BREAKPOINT * bp) //RemoveAllBreakPoints doesn't remove librarian breakpoints
|
|
||||||
{
|
{
|
||||||
if(bp->type == BPDLL)
|
EXCLUSIVE_ACQUIRE(LockDllBreakpoints);
|
||||||
LibrarianRemoveBreakPoint(bp->mod, bp->titantype);
|
dllBreakpoints.clear(); //RemoveAllBreakPoints doesn't remove librarian breakpoints
|
||||||
return true;
|
}
|
||||||
});
|
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
dbgcleartracestate();
|
dbgcleartracestate();
|
||||||
|
|
|
@ -79,6 +79,8 @@ const char* dbggetdebuggeeinitscript();
|
||||||
void dbgsetforeground();
|
void dbgsetforeground();
|
||||||
bool dbggetwintext(std::vector<std::string>* winTextList, const DWORD dwProcessId);
|
bool dbggetwintext(std::vector<std::string>* winTextList, const DWORD dwProcessId);
|
||||||
void dbgtracebrowserneedsupdate();
|
void dbgtracebrowserneedsupdate();
|
||||||
|
bool dbgsetdllbreakpoint(const char* mod, DWORD type, bool singleshoot);
|
||||||
|
bool dbgdeletedllbreakpoint(const char* mod, DWORD type);
|
||||||
|
|
||||||
void cbStep();
|
void cbStep();
|
||||||
void cbRtrStep();
|
void cbRtrStep();
|
||||||
|
@ -88,7 +90,6 @@ void cbMemoryBreakpoint(void* ExceptionAddress);
|
||||||
void cbHardwareBreakpoint(void* ExceptionAddress);
|
void cbHardwareBreakpoint(void* ExceptionAddress);
|
||||||
void cbUserBreakpoint();
|
void cbUserBreakpoint();
|
||||||
void cbDebugLoadLibBPX();
|
void cbDebugLoadLibBPX();
|
||||||
void cbLibrarianBreakpoint(void* lpData);
|
|
||||||
DWORD WINAPI threadDebugLoop(void* lpParameter);
|
DWORD WINAPI threadDebugLoop(void* lpParameter);
|
||||||
void cbTraceOverConditionalStep();
|
void cbTraceOverConditionalStep();
|
||||||
void cbTraceIntoConditionalStep();
|
void cbTraceIntoConditionalStep();
|
||||||
|
|
|
@ -73,6 +73,7 @@ enum SectionLock
|
||||||
LockTypeManager,
|
LockTypeManager,
|
||||||
LockModuleHashes,
|
LockModuleHashes,
|
||||||
LockFormatFunctions,
|
LockFormatFunctions,
|
||||||
|
LockDllBreakpoints,
|
||||||
|
|
||||||
// Number of elements in this enumeration. Must always be the last index.
|
// Number of elements in this enumeration. Must always be the last index.
|
||||||
LockLast
|
LockLast
|
||||||
|
|
Loading…
Reference in New Issue