1
0
Fork 0

Added async and rate limit logic to calls that tended to flood the gui thread

This commit is contained in:
justin 2016-07-05 00:44:54 -06:00
parent de39b65b1e
commit 2899acd0c7
9 changed files with 217 additions and 37 deletions

View File

@ -53,6 +53,13 @@ SCRIPT_EXPORT bool Script::Debug::DeleteBreakpoint(duint address)
char command[128] = "";
sprintf_s(command, "bc %p", address);
return DbgCmdExecDirect(command);
}
SCRIPT_EXPORT bool Script::Debug::DisableBreakpoint(duint address)
{
char command[128] = "";
sprintf_s(command, "bd %p", address);
return DbgCmdExecDirect(command);
}
SCRIPT_EXPORT bool Script::Debug::SetHardwareBreakpoint(duint address, HardwareType type)

View File

@ -23,6 +23,7 @@ namespace Script
SCRIPT_EXPORT void StepOut();
SCRIPT_EXPORT bool SetBreakpoint(duint address);
SCRIPT_EXPORT bool DeleteBreakpoint(duint address);
SCRIPT_EXPORT bool DisableBreakpoint(duint address);
SCRIPT_EXPORT bool SetHardwareBreakpoint(duint address, HardwareType type = HardwareExecute);
SCRIPT_EXPORT bool DeleteHardwareBreakpoint(duint address);
}; //Debug

View File

@ -24,6 +24,7 @@
#include "stackinfo.h"
#include "stringformat.h"
#include "TraceRecord.h"
#include "taskthread.h"
struct TraceCondition
{
@ -115,7 +116,7 @@ static DWORD WINAPI memMapThread(void* ptr)
{
if(bStopMemMapThread)
break;
Sleep(1);
Sleep(33);
}
// Execute the update only if the delta if >= 1 second
@ -127,7 +128,7 @@ static DWORD WINAPI memMapThread(void* ptr)
memMapThreadCounter = GetTickCount();
}
Sleep(50);
Sleep(1000);
}
return 0;
@ -264,6 +265,7 @@ duint dbggetdbgevents()
return InterlockedExchange(&DbgEvents, 0);
}
DWORD WINAPI updateCallStackThread(void* ptr)
{
stackupdatecallstack(duint(ptr));
@ -271,6 +273,12 @@ DWORD WINAPI updateCallStackThread(void* ptr)
return 0;
}
void updateCallStackAsync(duint ptr)
{
static TaskThread updateCallStackTask(updateCallStackThread);
updateCallStackTask.WakeUp(ptr);
}
DWORD WINAPI updateSEHChainThread(void* ptr)
{
GuiUpdateSEHChain();
@ -279,6 +287,12 @@ DWORD WINAPI updateSEHChainThread(void* ptr)
return 0;
}
void updateSEHChainAsync()
{
static TaskThread updateSEHChainTask(updateSEHChainThread);
updateSEHChainTask.WakeUp();
}
void DebugUpdateGui(duint disasm_addr, bool stack)
{
if(GuiIsUpdateDisabled())
@ -302,8 +316,8 @@ void DebugUpdateGui(duint disasm_addr, bool stack)
if(csp != cacheCsp)
{
InterlockedExchange(&cacheCsp, csp);
CloseHandle(CreateThread(nullptr, 0, updateCallStackThread, LPVOID(csp), 0, nullptr));
CloseHandle(CreateThread(nullptr, 0, updateSEHChainThread, nullptr, 0, nullptr));
updateCallStackAsync(csp);
updateSEHChainAsync();
}
char modname[MAX_MODULE_SIZE] = "";
char modtext[MAX_MODULE_SIZE * 2] = "";
@ -317,6 +331,26 @@ void DebugUpdateGui(duint disasm_addr, bool stack)
GuiUpdateAllViews();
GuiFocusView(GUI_DISASSEMBLY);
}
static DWORD WINAPI _debugUpdateGuiStack(void* disasm_addr)
{
DebugUpdateGui((duint)disasm_addr, true);
return 0;
}
static DWORD WINAPI _debugUpdateGuiNoStack(void* disasm_addr)
{
DebugUpdateGui((duint)disasm_addr, false);
return 0;
}
void DebugUpdateGuiAsync(duint disasm_addr, bool stack)
{
static TaskThread DebugUpdateGuiStackTask(_debugUpdateGuiStack);
static TaskThread DebugUpdateGuiNoStackTask(_debugUpdateGuiNoStack);
if(stack)
DebugUpdateGuiStackTask.WakeUp(disasm_addr);
else
DebugUpdateGuiNoStackTask.WakeUp(disasm_addr);
}
void DebugUpdateStack(duint dumpAddr, duint csp, bool forceDump)
{
@ -455,13 +489,23 @@ static bool getConditionValue(const char* expression)
return true;
}
static DWORD WINAPI _guiSetDebugState(void* state)
{
GuiSetDebugState((DBGSTATE)(int)state);
return 0;
}
void GuiSetDebugStateAsync(DBGSTATE state)
{
static TaskThread GuiSetDebugStateTask(_guiSetDebugState);
GuiSetDebugStateTask.WakeUp(state);
}
void cbPauseBreakpoint()
{
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
auto CIP = GetContextDataEx(hActiveThread, UE_CIP);
DeleteBPX(CIP);
GuiSetDebugState(paused);
DebugUpdateGui(CIP, true);
GuiSetDebugStateAsync(paused);
DebugUpdateGuiAsync(CIP, true);
//lock
lock(WAITID_RUN);
SetForegroundWindow(GuiGetWindowHandle());
@ -494,8 +538,8 @@ static void cbGenericBreakpoint(BP_TYPE bptype, void* ExceptionAddress = nullptr
{
SHARED_RELEASE();
dputs("Breakpoint reached not in list!");
GuiSetDebugState(paused);
DebugUpdateGui(GetContextDataEx(hActiveThread, UE_CIP), true);
GuiSetDebugStateAsync(paused);
DebugUpdateGuiAsync(GetContextDataEx(hActiveThread, UE_CIP), true);
//lock
lock(WAITID_RUN);
SetForegroundWindow(GuiGetWindowHandle());
@ -555,8 +599,8 @@ static void cbGenericBreakpoint(BP_TYPE bptype, void* ExceptionAddress = nullptr
default:
break;
}
GuiSetDebugState(paused);
DebugUpdateGui(CIP, true);
GuiSetDebugStateAsync(paused);
DebugUpdateGuiAsync(CIP, true);
}
// plugin interaction
@ -610,8 +654,8 @@ static void cbGenericBreakpoint(BP_TYPE bptype, void* ExceptionAddress = nullptr
default:
break;
}
GuiSetDebugState(paused);
DebugUpdateGui(CIP, true);
GuiSetDebugStateAsync(paused);
DebugUpdateGuiAsync(CIP, true);
PLUG_CB_PAUSEDEBUG pauseInfo;
pauseInfo.reserved = nullptr;
plugincbcall(CB_PAUSEDEBUG, &pauseInfo);
@ -668,8 +712,8 @@ void cbRunToUserCodeBreakpoint(void* ExceptionAddress)
pauseInfo.reserved = nullptr;
plugincbcall(CB_PAUSEDEBUG, &pauseInfo);
_dbg_dbgtraceexecute(CIP);
GuiSetDebugState(paused);
DebugUpdateGui(GetContextDataEx(hActiveThread, UE_CIP), true);
GuiSetDebugStateAsync(paused);
DebugUpdateGuiAsync(GetContextDataEx(hActiveThread, UE_CIP), true);
SetForegroundWindow(GuiGetWindowHandle());
bSkipExceptions = false;
wait(WAITID_RUN);
@ -839,9 +883,9 @@ void cbStep()
{
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
isStepping = false;
GuiSetDebugState(paused);
GuiSetDebugStateAsync(paused);
duint CIP = GetContextDataEx(hActiveThread, UE_CIP);
DebugUpdateGui(CIP, true);
DebugUpdateGuiAsync(CIP, true);
// Trace record
_dbg_dbgtraceexecute(CIP);
// Plugin interaction
@ -862,11 +906,11 @@ static void cbRtrFinalStep()
{
dbgcleartracecondition();
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
GuiSetDebugState(paused);
GuiSetDebugStateAsync(paused);
duint CIP = GetContextDataEx(hActiveThread, UE_CIP);
// Trace record
_dbg_dbgtraceexecute(CIP);
DebugUpdateGui(CIP, true);
DebugUpdateGuiAsync(CIP, true);
//lock
lock(WAITID_RUN);
SetForegroundWindow(GuiGetWindowHandle());
@ -1167,8 +1211,8 @@ static void cbCreateThread(CREATE_THREAD_DEBUG_INFO* CreateThread)
//update memory map
MemUpdateMap();
//update GUI
GuiSetDebugState(paused);
DebugUpdateGui(GetContextDataEx(hActiveThread, UE_CIP), true);
GuiSetDebugStateAsync(paused);
DebugUpdateGuiAsync(GetContextDataEx(hActiveThread, UE_CIP), true);
//lock
lock(WAITID_RUN);
SetForegroundWindow(GuiGetWindowHandle());
@ -1204,8 +1248,8 @@ static void cbExitThread(EXIT_THREAD_DEBUG_INFO* ExitThread)
if(settingboolget("Events", "ThreadEnd"))
{
//update GUI
GuiSetDebugState(paused);
DebugUpdateGui(GetContextDataEx(hActiveThread, UE_CIP), true);
GuiSetDebugStateAsync(paused);
DebugUpdateGuiAsync(GetContextDataEx(hActiveThread, UE_CIP), true);
//lock
lock(WAITID_RUN);
SetForegroundWindow(GuiGetWindowHandle());
@ -1222,9 +1266,9 @@ static void cbSystemBreakpoint(void* ExceptionData)
// Update GUI (this should be the first triggered event)
duint cip = GetContextDataEx(hActiveThread, UE_CIP);
GuiSetDebugState(running);
GuiSetDebugStateAsync(running);
GuiDumpAt(MemFindBaseAddr(cip, 0, true)); //dump somewhere
DebugUpdateGui(cip, true);
DebugUpdateGuiAsync(cip, true);
//log message
if(bIsAttached)
@ -1241,7 +1285,7 @@ static void cbSystemBreakpoint(void* ExceptionData)
if(bIsAttached ? settingboolget("Events", "AttachBreakpoint") : settingboolget("Events", "SystemBreakpoint"))
{
//lock
GuiSetDebugState(paused);
GuiSetDebugStateAsync(paused);
lock(WAITID_RUN);
SetForegroundWindow(GuiGetWindowHandle());
PLUG_CB_PAUSEDEBUG pauseInfo;
@ -1374,8 +1418,8 @@ static void cbLoadDll(LOAD_DLL_DEBUG_INFO* LoadDll)
{
bBreakOnNextDll = false;
//update GUI
GuiSetDebugState(paused);
DebugUpdateGui(GetContextDataEx(hActiveThread, UE_CIP), true);
GuiSetDebugStateAsync(paused);
DebugUpdateGuiAsync(GetContextDataEx(hActiveThread, UE_CIP), true);
//lock
lock(WAITID_RUN);
SetForegroundWindow(GuiGetWindowHandle());
@ -1405,8 +1449,8 @@ static void cbUnloadDll(UNLOAD_DLL_DEBUG_INFO* UnloadDll)
{
bBreakOnNextDll = false;
//update GUI
GuiSetDebugState(paused);
DebugUpdateGui(GetContextDataEx(hActiveThread, UE_CIP), true);
GuiSetDebugStateAsync(paused);
DebugUpdateGuiAsync(GetContextDataEx(hActiveThread, UE_CIP), true);
//lock
lock(WAITID_RUN);
SetForegroundWindow(GuiGetWindowHandle());
@ -1450,8 +1494,8 @@ static void cbOutputDebugString(OUTPUT_DEBUG_STRING_INFO* DebugString)
if(settingboolget("Events", "DebugStrings"))
{
//update GUI
GuiSetDebugState(paused);
DebugUpdateGui(GetContextDataEx(hActiveThread, UE_CIP), true);
GuiSetDebugStateAsync(paused);
DebugUpdateGuiAsync(GetContextDataEx(hActiveThread, UE_CIP), true);
//lock
lock(WAITID_RUN);
SetForegroundWindow(GuiGetWindowHandle());
@ -1489,10 +1533,10 @@ static void cbException(EXCEPTION_DEBUG_INFO* ExceptionData)
{
dputs("paused!");
SetNextDbgContinueStatus(DBG_CONTINUE);
GuiSetDebugState(paused);
GuiSetDebugStateAsync(paused);
//update memory map
MemUpdateMap();
DebugUpdateGui(GetContextDataEx(hActiveThread, UE_CIP), true);
DebugUpdateGuiAsync(GetContextDataEx(hActiveThread, UE_CIP), true);
//lock
lock(WAITID_RUN);
SetForegroundWindow(GuiGetWindowHandle());
@ -1545,8 +1589,8 @@ static void cbException(EXCEPTION_DEBUG_INFO* ExceptionData)
SetNextDbgContinueStatus(DBG_CONTINUE);
}
GuiSetDebugState(paused);
DebugUpdateGui(GetContextDataEx(hActiveThread, UE_CIP), true);
GuiSetDebugStateAsync(paused);
DebugUpdateGuiAsync(GetContextDataEx(hActiveThread, UE_CIP), true);
//lock
lock(WAITID_RUN);
SetForegroundWindow(GuiGetWindowHandle());
@ -2146,7 +2190,7 @@ static void debugLoopFunction(void* lpParameter, bool attach)
SetCustomHandler(UE_CH_DEBUGEVENT, (void*)cbDebugEvent);
//inform GUI we started without problems
GuiSetDebugState(initialized);
GuiSetDebugStateAsync(initialized);
GuiAddRecentFile(szFileName);
//set GUI title
@ -2199,7 +2243,7 @@ static void debugLoopFunction(void* lpParameter, bool attach)
ModClear();
ThreadClear();
TraceRecord.clear();
GuiSetDebugState(stopped);
GuiSetDebugStateAsync(stopped);
GuiUpdateAllViews();
dputs("Debugging stopped!");
varset("$hp", (duint)0, true);

View File

@ -69,6 +69,7 @@ bool dbgisdll();
void dbgsetattachevent(HANDLE handle);
void DebugUpdateGui(duint disasm_addr, bool stack);
void DebugUpdateStack(duint dumpAddr, duint csp, bool forceDump = false);
void GuiSetDebugStateAsync(DBGSTATE state);
void dbgsetskipexceptions(bool skip);
void dbgsetstepping(bool stepping);
void dbgsetispausedbyuser(bool b);

View File

@ -22,6 +22,7 @@
#include "label.h"
#include "bookmark.h"
#include "function.h"
#include "taskthread.h"
static bool bScyllaLoaded = false;
duint LoadLibThreadID;

95
src/dbg/taskthread.cpp Normal file
View File

@ -0,0 +1,95 @@
#include <Windows.h>
#include "taskthread.h"
#include <mutex>
#include <condition_variable>
#include <thread>
struct TaskThreadDetails
{
HANDLE threadHandle;
bool active = true;
bool pending = false;
void* arg = 0;
TaskThread::TaskFunction_t fn;
CRITICAL_SECTION access;
CONDITION_VARIABLE wakeup;
size_t minSleepTimeMs;
size_t wakeups = 0;
size_t execs = 0;
TaskThreadDetails()
{
InitializeCriticalSection(&access);
InitializeConditionVariable(&wakeup);
}
~TaskThreadDetails()
{
active = false;
pending = true;
{
EnterCriticalSection(&access);
WakeConditionVariable(&wakeup);
LeaveCriticalSection(&access);
}
WaitForSingleObject(threadHandle, INFINITE);
CloseHandle(threadHandle);
}
void WakeUp(void* _arg)
{
EnterCriticalSection(&access);
wakeups++;
arg = _arg;
pending = true;
WakeConditionVariable(&wakeup);
LeaveCriticalSection(&access);
}
void Loop()
{
void* argLatch = 0;
while(active)
{
{
EnterCriticalSection(&access);
while(pending == false)
SleepConditionVariableCS(&wakeup, &access, INFINITE);
argLatch = arg;
pending = false;
LeaveCriticalSection(&access);
}
if(active)
{
fn(argLatch);
std::this_thread::sleep_for(std::chrono::milliseconds(minSleepTimeMs));
execs++;
}
}
}
};
static DWORD WINAPI __task_loop(void* ptr)
{
((TaskThreadDetails*)ptr)->Loop();
return 0;
}
void TaskThread::WakeUp(void* arg)
{
details->WakeUp(arg);
}
TaskThread::TaskThread(TaskFunction_t fn,
size_t minSleepTimeMs,
_SECURITY_ATTRIBUTES* lpThreadAttributes,
SIZE_T dwStackSize)
{
details = new TaskThreadDetails();
details->fn = fn;
details->minSleepTimeMs = minSleepTimeMs;
details->threadHandle = CreateThread(lpThreadAttributes, dwStackSize, __task_loop, details, 0, 0);
}
TaskThread::~TaskThread()
{
delete details;
details = 0;
}

23
src/dbg/taskthread.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef _TASKTHREAD_H
#define _TASKTHREAD_H
#include "_global.h"
struct _SECURITY_ATTRIBUTES;
struct TaskThreadDetails;
class TaskThread
{
TaskThreadDetails* details = 0;
public:
typedef DWORD(WINAPI* TaskFunction_t)(void*);
void WakeUp(void* arg = 0);
template <typename T> void WakeUp(T arg = 0) { WakeUp((void*)arg); }
TaskThread(TaskFunction_t,
size_t minSleepTimeMs = 500,
_SECURITY_ATTRIBUTES* lpThreadAttributes = 0,
SIZE_T dwStackSize = 0);
~TaskThread();
};
#endif // _TASKTHREAD_H

View File

@ -74,6 +74,7 @@
<ClCompile Include="stringformat.cpp" />
<ClCompile Include="stringutils.cpp" />
<ClCompile Include="symbolinfo.cpp" />
<ClCompile Include="taskthread.cpp" />
<ClCompile Include="tcpconnections.cpp" />
<ClCompile Include="thread.cpp" />
<ClCompile Include="threading.cpp" />
@ -175,6 +176,7 @@
<ClInclude Include="recursiveanalysis.h" />
<ClInclude Include="reference.h" />
<ClInclude Include="serializablemap.h" />
<ClInclude Include="taskthread.h" />
<ClInclude Include="tcpconnections.h" />
<ClInclude Include="TraceRecord.h" />
<ClInclude Include="xrefs.h" />

View File

@ -335,6 +335,9 @@
<ClCompile Include="datainst_helper.cpp">
<Filter>Source Files\Utilities</Filter>
</ClCompile>
<ClCompile Include="taskthread.cpp">
<Filter>Source Files\Utilities</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="x64_dbg.h">
@ -757,5 +760,8 @@
<ClInclude Include="datainst_helper.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
<ClInclude Include="taskthread.h">
<Filter>Header Files\Utilities</Filter>
</ClInclude>
</ItemGroup>
</Project>