From 61fa77d3ac26ad5207934c2d01a910ea37b183a7 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Sat, 8 Aug 2015 15:55:59 +0200 Subject: [PATCH] DBG + GUI: don't try to set breakpoints on invalid TLS callbacks + added time wasted counter + added version number in menu bar --- x64_dbg_bridge/bridgemain.cpp | 10 +++ x64_dbg_bridge/bridgemain.h | 8 ++- x64_dbg_dbg/_exports.cpp | 3 + x64_dbg_dbg/debugger.cpp | 66 +++++++++++++++++-- x64_dbg_dbg/debugger.h | 1 + x64_dbg_gui/Project/Src/Bridge/Bridge.cpp | 4 ++ x64_dbg_gui/Project/Src/Bridge/Bridge.h | 1 + x64_dbg_gui/Project/Src/Gui/MainWindow.cpp | 12 ++++ .../Project/Src/Gui/TimeWastedCounter.cpp | 19 ++++++ .../Project/Src/Gui/TimeWastedCounter.h | 20 ++++++ x64_dbg_gui/Project/x64_dbg.pro | 6 +- 11 files changed, 139 insertions(+), 11 deletions(-) create mode 100644 x64_dbg_gui/Project/Src/Gui/TimeWastedCounter.cpp create mode 100644 x64_dbg_gui/Project/Src/Gui/TimeWastedCounter.h diff --git a/x64_dbg_bridge/bridgemain.cpp b/x64_dbg_bridge/bridgemain.cpp index 6473bbfd..d8ea8499 100644 --- a/x64_dbg_bridge/bridgemain.cpp +++ b/x64_dbg_bridge/bridgemain.cpp @@ -805,6 +805,11 @@ BRIDGE_IMPEXP bool DbgIsRunning() return !DbgIsRunLocked(); } +BRIDGE_IMPEXP duint DbgGetTimeWastedCounter() +{ + return _dbg_sendmessage(DBG_GET_TIME_WASTED_COUNTER, nullptr, nullptr); +} + BRIDGE_IMPEXP void GuiDisasmAt(duint addr, duint cip) { _gui_sendmessage(GUI_DISASSEMBLE_AT, (void*)addr, (void*)cip); @@ -1195,6 +1200,11 @@ BRIDGE_IMPEXP void GuiExecuteOnGuiThread(GUICALLBACK cbGuiThread) _gui_sendmessage(GUI_EXECUTE_ON_GUI_THREAD, cbGuiThread, nullptr); } +BRIDGE_IMPEXP void GuiUpdateTimeWastedCounter() +{ + _gui_sendmessage(GUI_UPDATE_TIME_WASTED_COUNTER, nullptr, nullptr); +} + BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { hInst = hinstDLL; diff --git a/x64_dbg_bridge/bridgemain.h b/x64_dbg_bridge/bridgemain.h index 84e7b1bb..e4364ff8 100644 --- a/x64_dbg_bridge/bridgemain.h +++ b/x64_dbg_bridge/bridgemain.h @@ -174,7 +174,8 @@ typedef enum DBG_WIN_EVENT, // param1=MSG* message, param2=long* result DBG_WIN_EVENT_GLOBAL, // param1=MSG* message, param2=unused DBG_INITIALIZE_LOCKS, // param1=unused, param2=unused - DBG_DEINITIALIZE_LOCKS // param1=unused, param2=unused + DBG_DEINITIALIZE_LOCKS, // param1=unused, param2=unused + DBG_GET_TIME_WASTED_COUNTER // param1=unused, param2=unused } DBGMSG; typedef enum @@ -691,6 +692,7 @@ BRIDGE_IMPEXP const DBGFUNCTIONS* DbgFunctions(); BRIDGE_IMPEXP bool DbgWinEvent(MSG* message, long* result); BRIDGE_IMPEXP bool DbgWinEventGlobal(MSG* message); BRIDGE_IMPEXP bool DbgIsRunning(); +BRIDGE_IMPEXP duint DbgGetTimeWastedCounter(); //Gui defines #define GUI_PLUGIN_MENU 0 @@ -772,7 +774,8 @@ typedef enum GUI_ADD_QWIDGET_TAB, // param1=QWidget*, param2=unused GUI_SHOW_QWIDGET_TAB, // param1=QWidget*, param2=unused GUI_CLOSE_QWIDGET_TAB, // param1=QWidget*, param2=unused - GUI_EXECUTE_ON_GUI_THREAD // param1=GUICALLBACK, param2=unused + GUI_EXECUTE_ON_GUI_THREAD, // param1=GUICALLBACK, param2=unused + GUI_UPDATE_TIME_WASTED_COUNTER // param1=unused, param2=unused } GUIMSG; //GUI Typedefs @@ -866,6 +869,7 @@ BRIDGE_IMPEXP void GuiAddQWidgetTab(void* qWidget); BRIDGE_IMPEXP void GuiShowQWidgetTab(void* qWidget); BRIDGE_IMPEXP void GuiCloseQWidgetTab(void* qWidget); BRIDGE_IMPEXP void GuiExecuteOnGuiThread(GUICALLBACK cbGuiThread); +BRIDGE_IMPEXP void GuiUpdateTimeWastedCounter(); #ifdef __cplusplus } diff --git a/x64_dbg_dbg/_exports.cpp b/x64_dbg_dbg/_exports.cpp index a617ef97..3de4c339 100644 --- a/x64_dbg_dbg/_exports.cpp +++ b/x64_dbg_dbg/_exports.cpp @@ -1006,6 +1006,9 @@ extern "C" DLL_EXPORT uint _dbg_sendmessage(DBGMSG type, void* param1, void* par SectionLockerGlobal::Deinitialize(); } break; + + case DBG_GET_TIME_WASTED_COUNTER: + return dbggettimewastedcounter(); } return 0; } diff --git a/x64_dbg_dbg/debugger.cpp b/x64_dbg_dbg/debugger.cpp index c03bee12..e90630f9 100644 --- a/x64_dbg_dbg/debugger.cpp +++ b/x64_dbg_dbg/debugger.cpp @@ -39,7 +39,10 @@ static HANDLE hEvent = 0; static HANDLE hProcess = 0; static HANDLE hMemMapThread = 0; static bool bStopMemMapThread = false; +static HANDLE hTimeWastedCounterThread = 0; +static bool bStopTimeWastedCounterThread = false; static String lastDebugText; +static uint timeWastedDebugging = 0; char szFileName[MAX_PATH] = ""; char szSymbolCachePath[MAX_PATH] = ""; char sqlitedb[deflen] = ""; @@ -72,17 +75,43 @@ static DWORD WINAPI memMapThread(void* ptr) return 0; } +static DWORD WINAPI timeWastedCounterThread(void* ptr) +{ + if (!BridgeSettingGetUint("Engine", "TimeWastedDebugging", &timeWastedDebugging)) + timeWastedDebugging = 0; + GuiUpdateTimeWastedCounter(); + while (!bStopTimeWastedCounterThread) + { + while (!DbgIsDebugging()) + { + if (bStopTimeWastedCounterThread) + break; + Sleep(1); + } + if (bStopTimeWastedCounterThread) + break; + timeWastedDebugging++; + GuiUpdateTimeWastedCounter(); + Sleep(1000); + } + BridgeSettingSetUint("Engine", "TimeWastedDebugging", timeWastedDebugging); + return 0; +} + void dbginit() { ExceptionCodeInit(); ErrorCodeInit(); - hMemMapThread = CreateThread(0, 0, memMapThread, 0, 0, 0); + hMemMapThread = CreateThread(nullptr, 0, memMapThread, nullptr, 0, nullptr); + hTimeWastedCounterThread = CreateThread(nullptr, 0, timeWastedCounterThread, nullptr, 0, nullptr); } void dbgstop() { bStopMemMapThread = true; + bStopTimeWastedCounterThread = true; WaitForThreadTermination(hMemMapThread); + WaitForThreadTermination(hTimeWastedCounterThread); } SIZE_T dbggetprivateusage(HANDLE hProcess, bool update) @@ -101,6 +130,11 @@ uint dbgdebuggedbase() return pDebuggedBase; } +uint dbggettimewastedcounter() +{ + return timeWastedDebugging; +} + bool dbgisrunning() { return !waitislocked(WAITID_RUN); @@ -675,11 +709,20 @@ static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo) else { uint ImageBase = GetPE32DataW(StringUtils::Utf8ToUtf16(DebugFileName).c_str(), 0, UE_IMAGEBASE); + int invalidCount = 0; for(unsigned int i = 0; i < NumberOfCallBacks; i++) { - sprintf(command, "bp "fhex",\"TLS Callback %d\",ss", TLSCallBacks()[i] - ImageBase + pDebuggedBase, i + 1); - cmddirectexec(dbggetcommandlist(), command); + uint callbackVA = TLSCallBacks()[i] - ImageBase + pDebuggedBase; + if (MemIsValidReadPtr(callbackVA)) + { + sprintf(command, "bp "fhex",\"TLS Callback %d\",ss", callbackVA, i + 1); + cmddirectexec(dbggetcommandlist(), command); + } + else + invalidCount++; } + if (invalidCount) + dprintf("%d invalid TLS callback addresses...\n", invalidCount); } } } @@ -871,14 +914,23 @@ static void cbLoadDll(LOAD_DLL_DEBUG_INFO* LoadDll) else { uint ImageBase = GetPE32DataW(StringUtils::Utf8ToUtf16(DLLDebugFileName).c_str(), 0, UE_IMAGEBASE); + int invalidCount = 0; for(unsigned int i = 0; i < NumberOfCallBacks; i++) { - if(bIsDebuggingThis) - sprintf(command, "bp "fhex",\"TLS Callback %d\",ss", TLSCallBacks()[i] - ImageBase + (uint)base, i + 1); + uint callbackVA = TLSCallBacks()[i] - ImageBase + (uint)base; + if (MemIsValidReadPtr(callbackVA)) + { + if (bIsDebuggingThis) + sprintf(command, "bp "fhex",\"TLS Callback %d\",ss", callbackVA, i + 1); + else + sprintf(command, "bp "fhex",\"TLS Callback %d (%s)\",ss", callbackVA, i + 1, modname); + cmddirectexec(dbggetcommandlist(), command); + } else - sprintf(command, "bp "fhex",\"TLS Callback %d (%s)\",ss", TLSCallBacks()[i] - ImageBase + (uint)base, i + 1, modname); - cmddirectexec(dbggetcommandlist(), command); + invalidCount++; } + if (invalidCount) + dprintf("%s invalid TLS callback addresses...\n", invalidCount); } } } diff --git a/x64_dbg_dbg/debugger.h b/x64_dbg_dbg/debugger.h index 3e3dcb98..74ce23f0 100644 --- a/x64_dbg_dbg/debugger.h +++ b/x64_dbg_dbg/debugger.h @@ -77,6 +77,7 @@ SIZE_T dbggetprivateusage(HANDLE hProcess, bool update = false); void dbginit(); void dbgstop(); uint dbgdebuggedbase(); +uint dbggettimewastedcounter(); bool dbgisrunning(); bool dbgisdll(); void dbgsetattachevent(HANDLE handle); diff --git a/x64_dbg_gui/Project/Src/Bridge/Bridge.cpp b/x64_dbg_gui/Project/Src/Bridge/Bridge.cpp index a79fe5a8..34cb046e 100644 --- a/x64_dbg_gui/Project/Src/Bridge/Bridge.cpp +++ b/x64_dbg_gui/Project/Src/Bridge/Bridge.cpp @@ -485,6 +485,10 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2) GuiAddLogMessage(QString().sprintf("thread id (bridge) %X\n", GetCurrentThreadId()).toUtf8().constData()); emit executeOnGuiThread(param1); break; + + case GUI_UPDATE_TIME_WASTED_COUNTER: + emit updateTimeWastedCounter(); + break; } return nullptr; } diff --git a/x64_dbg_gui/Project/Src/Bridge/Bridge.h b/x64_dbg_gui/Project/Src/Bridge/Bridge.h index 60bdac1d..753ce605 100644 --- a/x64_dbg_gui/Project/Src/Bridge/Bridge.h +++ b/x64_dbg_gui/Project/Src/Bridge/Bridge.h @@ -109,6 +109,7 @@ signals: void showQWidgetTab(QWidget* qWidget); void closeQWidgetTab(QWidget* qWidget); void executeOnGuiThread(void* cbGuiThread); + void updateTimeWastedCounter(); private: QMutex* mBridgeMutex; diff --git a/x64_dbg_gui/Project/Src/Gui/MainWindow.cpp b/x64_dbg_gui/Project/Src/Gui/MainWindow.cpp index 47e26404..1b713b4a 100644 --- a/x64_dbg_gui/Project/Src/Gui/MainWindow.cpp +++ b/x64_dbg_gui/Project/Src/Gui/MainWindow.cpp @@ -12,11 +12,23 @@ #include "ShortcutsDialog.h" #include "AttachDialog.h" #include "LineEditDialog.h" +#include "TimeWastedCounter.h" MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); + //build information + QString buildText = QString().sprintf("v%d, "__DATE__, BridgeGetDbgVersion()); + QAction* buildInfo = new QAction(buildText, this); + buildInfo->setEnabled(false); + ui->menuBar->addAction(buildInfo); + + //time wasted counter + QAction* timeWastedLabel = new QAction(this); + ui->menuBar->addAction(timeWastedLabel); + TimeWastedCounter* timeWastedCounter = new TimeWastedCounter(this, timeWastedLabel); + //setup bridge signals connect(Bridge::getBridge(), SIGNAL(updateWindowTitle(QString)), this, SLOT(updateWindowTitleSlot(QString))); connect(Bridge::getBridge(), SIGNAL(addRecentFile(QString)), this, SLOT(addRecentFile(QString))); diff --git a/x64_dbg_gui/Project/Src/Gui/TimeWastedCounter.cpp b/x64_dbg_gui/Project/Src/Gui/TimeWastedCounter.cpp new file mode 100644 index 00000000..b3532f58 --- /dev/null +++ b/x64_dbg_gui/Project/Src/Gui/TimeWastedCounter.cpp @@ -0,0 +1,19 @@ +#include "TimeWastedCounter.h" +#include "Bridge.h" + +TimeWastedCounter::TimeWastedCounter(QObject* parent, QAction* label) + : QObject(parent), mLabel(label) +{ + mLabel->setEnabled(false); + connect(Bridge::getBridge(), SIGNAL(updateTimeWastedCounter()), this, SLOT(updateTimeWastedCounter())); +} + +void TimeWastedCounter::updateTimeWastedCounter() +{ + duint timeWasted = DbgGetTimeWastedCounter(); + int days = timeWasted / (60 * 60 * 24); + int hours = (timeWasted / (60 * 60)) % 24; + int minutes = (timeWasted / 60) % 60; + int seconds = timeWasted % 60; + mLabel->setText(QString().sprintf("Time Wasted Debugging: %d:%02d:%02d:%02d", days, hours, minutes, seconds)); +} diff --git a/x64_dbg_gui/Project/Src/Gui/TimeWastedCounter.h b/x64_dbg_gui/Project/Src/Gui/TimeWastedCounter.h new file mode 100644 index 00000000..a0af3adf --- /dev/null +++ b/x64_dbg_gui/Project/Src/Gui/TimeWastedCounter.h @@ -0,0 +1,20 @@ +#ifndef TIMEWASTEDCOUNTER_H +#define TIMEWASTEDCOUNTER_H + +#include +#include + +class TimeWastedCounter : public QObject +{ + Q_OBJECT +public: + explicit TimeWastedCounter(QObject* parent, QAction* label); + +private slots: + void updateTimeWastedCounter(); + +private: + QAction* mLabel; +}; + +#endif // TIMEWASTEDCOUNTER_H diff --git a/x64_dbg_gui/Project/x64_dbg.pro b/x64_dbg_gui/Project/x64_dbg.pro index ba988e77..273c4423 100644 --- a/x64_dbg_gui/Project/x64_dbg.pro +++ b/x64_dbg_gui/Project/x64_dbg.pro @@ -92,7 +92,8 @@ SOURCES += \ Src/Gui/SourceViewerManager.cpp \ Src/Gui/SourceView.cpp \ Src/Utils/ValidateExpressionThread.cpp \ - Src/Utils/MainWindowCloseThread.cpp + Src/Utils/MainWindowCloseThread.cpp \ + Src/Gui/TimeWastedCounter.cpp HEADERS += \ @@ -164,7 +165,8 @@ HEADERS += \ Src/Gui/SourceView.h \ Src/Utils/StringUtil.h \ Src/Utils/ValidateExpressionThread.h \ - Src/Utils/MainWindowCloseThread.h + Src/Utils/MainWindowCloseThread.h \ + Src/Gui/TimeWastedCounter.h INCLUDEPATH += \