better thread and process housekeeping

This commit is contained in:
Mr. eXoDia 2015-03-28 01:33:14 +01:00
parent ed7d8e453f
commit 6ddcb2d798
5 changed files with 133 additions and 87 deletions

View File

@ -2,20 +2,24 @@
namespace GleeBug namespace GleeBug
{ {
void Debugger::createProcessEvent(CREATE_PROCESS_DEBUG_INFO* createProcess) void Debugger::createProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess)
{ {
//process housekeeping //process housekeeping
ProcessInfo process(createProcess->hProcess, ProcessInfo process(createProcess.hProcess,
createProcess->hThread, createProcess.hThread,
_debugEvent.dwProcessId, _debugEvent.dwProcessId,
_debugEvent.dwThreadId); _debugEvent.dwThreadId);
_processes.insert({ process.dwProcessId, process }); _processes.insert({ process.dwProcessId, process });
//set the current process and current thread
_curProcess = &_processes[process.dwProcessId];
_curProcess->curThread = &_curProcess->threads[process.dwMainThreadId];
//call the callback //call the callback
cbCreateProcessEvent(createProcess); cbCreateProcessEvent(createProcess);
} }
void Debugger::exitProcessEvent(EXIT_PROCESS_DEBUG_INFO* exitProcess) void Debugger::exitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess)
{ {
//check if the terminated process is the main debuggee //check if the terminated process is the main debuggee
if (_debugEvent.dwProcessId == _mainProcess.dwProcessId) if (_debugEvent.dwProcessId == _mainProcess.dwProcessId)
@ -28,17 +32,20 @@ namespace GleeBug
_processes.erase(_debugEvent.dwProcessId); _processes.erase(_debugEvent.dwProcessId);
} }
void Debugger::createThreadEvent(CREATE_THREAD_DEBUG_INFO* createThread) void Debugger::createThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread)
{ {
//thread housekeeping //thread housekeeping
ThreadInfo thread(_debugEvent.dwThreadId, createThread->hThread, createThread->lpThreadLocalBase, createThread->lpStartAddress); ThreadInfo thread(_debugEvent.dwThreadId, createThread.hThread, createThread.lpThreadLocalBase, createThread.lpStartAddress);
_processes[_debugEvent.dwProcessId].threads.insert({ thread.dwThreadId, thread }); _curProcess->threads.insert({ thread.dwThreadId, thread });
//set the current thread
_curProcess->curThread = &_curProcess->threads[thread.dwThreadId];
//call the callback //call the callback
cbCreateThreadEvent(createThread); cbCreateThreadEvent(createThread);
} }
void Debugger::exitThreadEvent(EXIT_THREAD_DEBUG_INFO* exitThread) void Debugger::exitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread)
{ {
//call the callback //call the callback
cbExitThreadEvent(exitThread); cbExitThreadEvent(exitThread);
@ -47,37 +54,27 @@ namespace GleeBug
_processes[_debugEvent.dwProcessId].threads.erase(_debugEvent.dwThreadId); _processes[_debugEvent.dwProcessId].threads.erase(_debugEvent.dwThreadId);
} }
void Debugger::loadDllEvent(LOAD_DLL_DEBUG_INFO* loadDll) void Debugger::loadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll)
{ {
cbLoadDllEvent(loadDll); cbLoadDllEvent(loadDll);
} }
void Debugger::unloadDllEvent(UNLOAD_DLL_DEBUG_INFO* unloadDll) void Debugger::unloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll)
{ {
cbUnloadDllEvent(unloadDll); cbUnloadDllEvent(unloadDll);
} }
void Debugger::exceptionEvent(EXCEPTION_DEBUG_INFO* exceptionInfo) void Debugger::exceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo)
{ {
switch (exceptionInfo->ExceptionRecord.ExceptionCode){
case EXCEPTION_SINGLE_STEP:
cbException_single_spep(&exceptionInfo->ExceptionRecord);
break;
case EXCEPTION_BREAKPOINT:
cbExcpetion_breakpoint(&exceptionInfo->ExceptionRecord);
break;
default:
cbExceptionEvent(exceptionInfo); cbExceptionEvent(exceptionInfo);
break;
}
} }
void Debugger::debugStringEvent(OUTPUT_DEBUG_STRING_INFO* debugString) void Debugger::debugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString)
{ {
cbDebugStringEvent(debugString); cbDebugStringEvent(debugString);
} }
void Debugger::ripEvent(RIP_INFO* rip) void Debugger::ripEvent(const RIP_INFO & rip)
{ {
cbRipEvent(rip); cbRipEvent(rip);
} }
@ -91,34 +88,46 @@ namespace GleeBug
if (!WaitForDebugEvent(&_debugEvent, INFINITE)) if (!WaitForDebugEvent(&_debugEvent, INFINITE))
break; break;
//set the current process and thread
if (_processes.count(_debugEvent.dwProcessId))
{
_curProcess = &_processes[_debugEvent.dwProcessId];
if (_curProcess->threads.count(_debugEvent.dwThreadId))
_curProcess->curThread = &_curProcess->threads[_debugEvent.dwThreadId];
else
_curProcess->curThread = nullptr;
}
else
_curProcess = nullptr;
switch (_debugEvent.dwDebugEventCode) switch (_debugEvent.dwDebugEventCode)
{ {
case CREATE_PROCESS_DEBUG_EVENT: case CREATE_PROCESS_DEBUG_EVENT:
createProcessEvent(&_debugEvent.u.CreateProcessInfo); createProcessEvent(_debugEvent.u.CreateProcessInfo);
break; break;
case EXIT_PROCESS_DEBUG_EVENT: case EXIT_PROCESS_DEBUG_EVENT:
exitProcessEvent(&_debugEvent.u.ExitProcess); exitProcessEvent(_debugEvent.u.ExitProcess);
break; break;
case CREATE_THREAD_DEBUG_EVENT: case CREATE_THREAD_DEBUG_EVENT:
createThreadEvent(&_debugEvent.u.CreateThread); createThreadEvent(_debugEvent.u.CreateThread);
break; break;
case EXIT_THREAD_DEBUG_EVENT: case EXIT_THREAD_DEBUG_EVENT:
exitThreadEvent(&_debugEvent.u.ExitThread); exitThreadEvent(_debugEvent.u.ExitThread);
break; break;
case LOAD_DLL_DEBUG_EVENT: case LOAD_DLL_DEBUG_EVENT:
loadDllEvent(&_debugEvent.u.LoadDll); loadDllEvent(_debugEvent.u.LoadDll);
break; break;
case UNLOAD_DLL_DEBUG_EVENT: case UNLOAD_DLL_DEBUG_EVENT:
unloadDllEvent(&_debugEvent.u.UnloadDll); unloadDllEvent(_debugEvent.u.UnloadDll);
break; break;
case EXCEPTION_DEBUG_EVENT: case EXCEPTION_DEBUG_EVENT:
exceptionEvent(&_debugEvent.u.Exception); exceptionEvent(_debugEvent.u.Exception);
break; break;
case OUTPUT_DEBUG_STRING_EVENT: case OUTPUT_DEBUG_STRING_EVENT:
debugStringEvent(&_debugEvent.u.DebugString); debugStringEvent(_debugEvent.u.DebugString);
break; break;
case RIP_EVENT: case RIP_EVENT:
ripEvent(&_debugEvent.u.RipInfo); ripEvent(_debugEvent.u.RipInfo);
break; break;
} }

View File

@ -17,6 +17,7 @@ namespace GleeBug
DWORD dwMainThreadId; DWORD dwMainThreadId;
ThreadMap threads; ThreadMap threads;
ThreadInfo* curThread;
ProcessInfo() {} //fixes a 'no default constructor available' error ProcessInfo() {} //fixes a 'no default constructor available' error

View File

@ -15,6 +15,8 @@ namespace GleeBug
ULONG_PTR lpThreadLocalBase; ULONG_PTR lpThreadLocalBase;
ULONG_PTR lpStartAddress; ULONG_PTR lpStartAddress;
ThreadInfo() {}
ThreadInfo(DWORD dwThreadId, HANDLE hThread, LPVOID lpThreadLocalBase, LPVOID lpStartAddress) ThreadInfo(DWORD dwThreadId, HANDLE hThread, LPVOID lpThreadLocalBase, LPVOID lpStartAddress)
{ {
this->dwThreadId = dwThreadId; this->dwThreadId = dwThreadId;

View File

@ -11,7 +11,7 @@ namespace GleeBug
*/ */
class Debugger class Debugger
{ {
public: public: //public functionality
/** /**
\brief Constructs the Debugger instance. \brief Constructs the Debugger instance.
*/ */
@ -45,89 +45,123 @@ namespace GleeBug
*/ */
void Start(); void Start();
protected: protected: //callbacks
/** /**
\brief Process creation debug event callback. Provide an implementation to use this callback. \brief Process creation debug event callback. Provide an implementation to use this callback.
\param createProcess Information about the process created. \param createProcess Information about the process created.
*/ */
virtual void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO* createProcess) {}; virtual void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess) {};
/** /**
\brief Process termination debug event callback. Provide an implementation to use this callback. \brief Process termination debug event callback. Provide an implementation to use this callback.
\param exitProcess Information about the process terminated. \param exitProcess Information about the process terminated.
*/ */
virtual void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO* exitProcess) {}; virtual void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess) {};
/** /**
\brief Thread creation debug event callback. Provide an implementation to use this callback. \brief Thread creation debug event callback. Provide an implementation to use this callback.
\param createThread Information about the thread created. \param createThread Information about the thread created.
*/ */
virtual void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO* createThread) {}; virtual void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread) {};
/** /**
\brief Thread termination debug event callback. Provide an implementation to use this callback. \brief Thread termination debug event callback. Provide an implementation to use this callback.
\param exitThread Information about the thread terminated. \param exitThread Information about the thread terminated.
*/ */
virtual void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO* exitThread) {}; virtual void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread) {};
/** /**
\brief DLL load debug event callback. Provide an implementation to use this callback. \brief DLL load debug event callback. Provide an implementation to use this callback.
\param loadDll Information about the DLL loaded. \param loadDll Information about the DLL loaded.
*/ */
virtual void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO* loadDll) {}; virtual void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll) {};
/** /**
\brief DLL unload debug event callback. Provide an implementation to use this callback. \brief DLL unload debug event callback. Provide an implementation to use this callback.
\param unloadDll Information about the DLL unloaded. \param unloadDll Information about the DLL unloaded.
*/ */
virtual void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO* unloadDll) {}; virtual void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll) {};
/** /**
\brief Exception debug event callback. Provide an implementation to use this callback. \brief Exception debug event callback. Provide an implementation to use this callback.
\param exceptionInfo Information about the exception. \param exceptionInfo Information about the exception.
*/ */
virtual void cbExceptionEvent(const EXCEPTION_DEBUG_INFO* exceptionInfo) {}; virtual void cbExceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo) {};
/*
single step event
these will execute instead of cbExceptionEvent.
*/
virtual void cbException_single_spep(EXCEPTION_RECORD* except_inf) {};
/*
breakpoint event
Will also execute instead of cbExceptionEvent.
*/
virtual void cbExcpetion_breakpoint(EXCEPTION_RECORD* except_inf) {};
/** /**
\brief Debug string debug event callback. Provide an implementation to use this callback. \brief Debug string debug event callback. Provide an implementation to use this callback.
\param debugString Information about the debug string. \param debugString Information about the debug string.
*/ */
virtual void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO* debugString) {}; virtual void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString) {};
/** /**
\brief RIP debug event callback. Provide an implementation to use this callback. \brief RIP debug event callback. Provide an implementation to use this callback.
\param rip Information about the RIP event. \param rip Information about the RIP event.
*/ */
virtual void cbRipEvent(const RIP_INFO* rip) {}; virtual void cbRipEvent(const RIP_INFO & rip) {};
protected: //core functionality
/**
\brief Process creation debug event. Do not override this unless you know what you are doing!
\param createProcess Information about the process created.
*/
virtual void createProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess);
virtual void createProcessEvent(CREATE_PROCESS_DEBUG_INFO* createProcess); /**
virtual void exitProcessEvent(EXIT_PROCESS_DEBUG_INFO* exitProcess); \brief Process termination debug event. Do not override this unless you know what you are doing!
virtual void createThreadEvent(CREATE_THREAD_DEBUG_INFO* createThread); \param exitProcess Information about the process terminated.
virtual void exitThreadEvent(EXIT_THREAD_DEBUG_INFO* exitThread); */
virtual void loadDllEvent(LOAD_DLL_DEBUG_INFO* loadDll); virtual void exitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess);
virtual void unloadDllEvent(UNLOAD_DLL_DEBUG_INFO* unloadDll);
virtual void exceptionEvent(EXCEPTION_DEBUG_INFO* exceptionInfo);
virtual void debugStringEvent(OUTPUT_DEBUG_STRING_INFO* debugString);
virtual void ripEvent(RIP_INFO* rip);
/**
\brief Thread creation debug event. Do not override this unless you know what you are doing!
\param createThread Information about the thread created.
*/
virtual void createThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread);
/**
\brief Thread termination debug event. Do not override this unless you know what you are doing!
\param exitThread Information about the thread terminated.
*/
virtual void exitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread);
/**
\brief DLL load debug event. Do not override this unless you know what you are doing!
\param loadDll Information about the DLL loaded.
*/
virtual void loadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll);
/**
\brief DLL unload debug event. Do not override this unless you know what you are doing!
\param unloadDll Information about the DLL unloaded.
*/
virtual void unloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll);
/**
\brief Exception debug event. Do not override this unless you know what you are doing!
\param exceptionInfo Information about the exception.
*/
virtual void exceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo);
/**
\brief Debug string debug event. Do not override this unless you know what you are doing!
\param debugString Information about the debug string.
*/
virtual void debugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString);
/**
\brief RIP debug event. Do not override this unless you know what you are doing!
\param rip Information about the RIP event.
*/
virtual void ripEvent(const RIP_INFO & rip);
protected: //variables
PROCESS_INFORMATION _mainProcess; PROCESS_INFORMATION _mainProcess;
DWORD _continueStatus; DWORD _continueStatus;
bool _breakDebugger; bool _breakDebugger;
DEBUG_EVENT _debugEvent; DEBUG_EVENT _debugEvent;
ProcessMap _processes; ProcessMap _processes;
ProcessInfo* _curProcess;
}; };
}; };

View File

@ -6,59 +6,59 @@
class MyDebugger : public GleeBug::Debugger class MyDebugger : public GleeBug::Debugger
{ {
protected: protected:
virtual void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO* createProcess) virtual void cbCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO & createProcess)
{ {
printf("Process %d created with entry 0x%p\n", _debugEvent.dwProcessId, createProcess->lpStartAddress); printf("Process %d created with entry 0x%p\n", _debugEvent.dwProcessId, createProcess.lpStartAddress);
}; };
virtual void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO* exitProcess) virtual void cbExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO & exitProcess)
{ {
printf("Process %d terminated with exit code 0x%08X\n", _debugEvent.dwProcessId, exitProcess->dwExitCode); printf("Process %d terminated with exit code 0x%08X\n", _debugEvent.dwProcessId, exitProcess.dwExitCode);
} }
virtual void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO* createThread) virtual void cbCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO & createThread)
{ {
printf("Thread %d created with entry 0x%p\n", _debugEvent.dwThreadId, createThread->lpStartAddress); printf("Thread %d created with entry 0x%p\n", _debugEvent.dwThreadId, createThread.lpStartAddress);
}; };
virtual void cbException_single_spep(EXCEPTION_RECORD* except_inf) virtual void cbException_single_spep(EXCEPTION_RECORD & except_inf)
{ {
printf("a single step occurred at location 0x%X", except_inf->ExceptionAddress); printf("a single step occurred at location 0x%X", except_inf.ExceptionAddress);
}; };
virtual void cbExcpetion_breakpoint(EXCEPTION_RECORD* except_inf) virtual void cbExcpetion_breakpoint(EXCEPTION_RECORD & except_inf)
{ {
printf("a breakpoint occurred at location 0x%X", except_inf->ExceptionAddress); printf("a breakpoint occurred at location 0x%X", except_inf.ExceptionAddress);
}; };
virtual void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO* exitThread) virtual void cbExitThreadEvent(const EXIT_THREAD_DEBUG_INFO & exitThread)
{ {
printf("Thread %d terminated with exit code 0x%08X\n", _debugEvent.dwThreadId, exitThread->dwExitCode); printf("Thread %d terminated with exit code 0x%08X\n", _debugEvent.dwThreadId, exitThread.dwExitCode);
}; };
virtual void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO* loadDll) virtual void cbLoadDllEvent(const LOAD_DLL_DEBUG_INFO & loadDll)
{ {
printf("DLL loaded at 0x%p\n", loadDll->lpBaseOfDll); printf("DLL loaded at 0x%p\n", loadDll.lpBaseOfDll);
}; };
virtual void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO* unloadDll) virtual void cbUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO & unloadDll)
{ {
printf("DLL 0x%p unloaded\n", unloadDll->lpBaseOfDll); printf("DLL 0x%p unloaded\n", unloadDll.lpBaseOfDll);
}; };
virtual void cbExceptionEvent(const EXCEPTION_DEBUG_INFO* exceptionInfo) virtual void cbExceptionEvent(const EXCEPTION_DEBUG_INFO & exceptionInfo)
{ {
printf("Exception with code 0x%08X\n", exceptionInfo->ExceptionRecord); printf("Exception with code 0x%08X\n", exceptionInfo.ExceptionRecord);
}; };
virtual void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO* debugString) virtual void cbDebugStringEvent(const OUTPUT_DEBUG_STRING_INFO & debugString)
{ {
printf("Debug string at 0x%p with length %d\n", debugString->lpDebugStringData, debugString->nDebugStringLength); printf("Debug string at 0x%p with length %d\n", debugString.lpDebugStringData, debugString.nDebugStringLength);
}; };
virtual void cbRipEvent(const RIP_INFO* rip) virtual void cbRipEvent(const RIP_INFO & rip)
{ {
printf("RIP event type 0x%X, error 0x%X", rip->dwType, rip->dwError); printf("RIP event type 0x%X, error 0x%X", rip.dwType, rip.dwError);
}; };
}; };