From b07611387f87c915492bb97092439f0f1a35be53 Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Tue, 19 Dec 2017 22:14:56 +0100 Subject: [PATCH] GUI: implement initial version of ZehSymbolTable beware of race conditions, but it appears to kinda work --- src/bridge/bridgemain.cpp | 10 ++++ src/bridge/bridgemain.h | 8 ++- src/dbg/_exports.cpp | 12 ++++ src/dbg/symbolsourcepdb.cpp | 11 ++++ src/gui/Src/BasicView/AbstractStdTable.cpp | 1 + src/gui/Src/Bridge/Bridge.cpp | 5 ++ src/gui/Src/Gui/SymbolView.cpp | 25 +++++++- src/gui/Src/Gui/SymbolView.h | 6 ++ src/gui/Src/Gui/ZehSymbolTable.cpp | 66 ++++++++++++++++++++++ src/gui/Src/Gui/ZehSymbolTable.h | 27 +++++++++ src/gui/x64dbg.pro | 6 +- src/x64dbg_translations.pro | 6 +- 12 files changed, 174 insertions(+), 9 deletions(-) create mode 100644 src/gui/Src/Gui/ZehSymbolTable.cpp create mode 100644 src/gui/Src/Gui/ZehSymbolTable.h diff --git a/src/bridge/bridgemain.cpp b/src/bridge/bridgemain.cpp index 3d924ca0..a745c44d 100644 --- a/src/bridge/bridgemain.cpp +++ b/src/bridge/bridgemain.cpp @@ -1075,6 +1075,11 @@ BRIDGE_IMPEXP void DbgMenuPrepare(int hMenu) _dbg_sendmessage(DBG_MENU_PREPARE, (void*)hMenu, nullptr); } +BRIDGE_IMPEXP void DbgGetSymbolInfo(void* symbol, SYMBOLINFO* info) +{ + _dbg_sendmessage(DBG_GET_SYMBOL_INFO, symbol, info); +} + BRIDGE_IMPEXP const char* GuiTranslateText(const char* Source) { EnterCriticalSection(&csTranslate); @@ -1690,6 +1695,11 @@ BRIDGE_IMPEXP void GuiOpenTraceFile(const char* fileName) _gui_sendmessage(GUI_OPEN_TRACE_FILE, (void*)fileName, nullptr); } +BRIDGE_IMPEXP void GuiSetModuleSymbols(duint base, ListOf(void*) symbols) +{ + _gui_sendmessage(GUI_SET_MODULE_SYMBOLS, (void*)base, symbols); +} + BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { hInst = hinstDLL; diff --git a/src/bridge/bridgemain.h b/src/bridge/bridgemain.h index 6d719f6b..8785a01e 100644 --- a/src/bridge/bridgemain.h +++ b/src/bridge/bridgemain.h @@ -308,7 +308,8 @@ typedef enum DBG_GET_PEB_ADDRESS, // param1=DWORD ProcessId, param2=unused DBG_GET_TEB_ADDRESS, // param1=DWORD ThreadId, param2=unused DBG_ANALYZE_FUNCTION, // param1=BridgeCFGraphList* graph, param2=duint entry - DBG_MENU_PREPARE // param1=int hMenu, param2=unused + DBG_MENU_PREPARE, // param1=int hMenu, param2=unused + DBG_GET_SYMBOL_INFO, // param1=void* symbol, param2=SYMBOLINFO* info } DBGMSG; typedef enum @@ -1012,6 +1013,7 @@ BRIDGE_IMPEXP duint DbgGetTebAddress(DWORD ThreadId); BRIDGE_IMPEXP bool DbgAnalyzeFunction(duint entry, BridgeCFGraphList* graph); BRIDGE_IMPEXP duint DbgEval(const char* expression, bool* success = 0); BRIDGE_IMPEXP void DbgMenuPrepare(int hMenu); +BRIDGE_IMPEXP void DbgGetSymbolInfo(void* symbol, SYMBOLINFO* info); //Gui defines #define GUI_PLUGIN_MENU 0 @@ -1139,7 +1141,8 @@ typedef enum GUI_MENU_REMOVE, // param1=int hEntryMenu, param2=unused GUI_REF_ADDCOMMAND, // param1=const char* title, param2=const char* command GUI_OPEN_TRACE_FILE, // param1=const char* file name,param2=unused - GUI_UPDATE_TRACE_BROWSER // param1=unused, param2=unused + GUI_UPDATE_TRACE_BROWSER, // param1=unused, param2=unused + GUI_SET_MODULE_SYMBOLS, // param1=duint base, param2=ListOf(void*) symbols } GUIMSG; //GUI Typedefs @@ -1316,6 +1319,7 @@ BRIDGE_IMPEXP void GuiFlushLog(); BRIDGE_IMPEXP void GuiReferenceAddCommand(const char* title, const char* command); BRIDGE_IMPEXP void GuiUpdateTraceBrowser(); BRIDGE_IMPEXP void GuiOpenTraceFile(const char* fileName); +BRIDGE_IMPEXP void GuiSetModuleSymbols(duint base, ListOf(void*) symbols); #ifdef __cplusplus } diff --git a/src/dbg/_exports.cpp b/src/dbg/_exports.cpp index 00b50cce..b8891d07 100644 --- a/src/dbg/_exports.cpp +++ b/src/dbg/_exports.cpp @@ -1472,6 +1472,18 @@ extern "C" DLL_EXPORT duint _dbg_sendmessage(DBGMSG type, void* param1, void* pa plugincbcall(CB_MENUPREPARE, &info); } break; + + case DBG_GET_SYMBOL_INFO: + { + //hack^2 + auto real = (SymbolInfo*)param1; + auto fake = (SYMBOLINFO*)param2; + fake->addr = real->addr; + fake->decoratedSymbol = (char*)real->decoratedName.c_str(); + fake->undecoratedSymbol = (char*)real->undecoratedName.c_str(); + fake->isImported = strncmp(fake->decoratedSymbol, "__imp_", 6) == 0; + } + break; } return 0; } diff --git a/src/dbg/symbolsourcepdb.cpp b/src/dbg/symbolsourcepdb.cpp index 752ea8c5..181d35d9 100644 --- a/src/dbg/symbolsourcepdb.cpp +++ b/src/dbg/symbolsourcepdb.cpp @@ -166,6 +166,17 @@ bool SymbolSourcePDB::loadSymbolsAsync(String path) dprintf("Loaded %d symbols in %.03f\n", _sym.size(), secs); + ListInfo blub; + blub.count = _sym.size(); + blub.size = blub.count * sizeof(void*); + std::vector fuck; + fuck.resize(_sym.size()); + size_t i = 0; + for(auto it = _sym.begin(); it != _sym.end(); ++it) + fuck[i++] = &it->second; + blub.data = fuck.data(); + GuiSetModuleSymbols(_imageBase, &blub); + GuiUpdateAllViews(); return true; diff --git a/src/gui/Src/BasicView/AbstractStdTable.cpp b/src/gui/Src/BasicView/AbstractStdTable.cpp index 71ad85c1..d430671b 100644 --- a/src/gui/Src/BasicView/AbstractStdTable.cpp +++ b/src/gui/Src/BasicView/AbstractStdTable.cpp @@ -707,6 +707,7 @@ void AbstractStdTable::headerButtonPressedSlot(int col) void AbstractStdTable::reloadData() { + //TODO: do this on request, not every time reloadData is called... if(mSort.column != -1) //re-sort if the user wants to sort { sortRows(mSort.column, mSort.ascending); diff --git a/src/gui/Src/Bridge/Bridge.cpp b/src/gui/Src/Bridge/Bridge.cpp index 13a191fd..77fc898d 100644 --- a/src/gui/Src/Bridge/Bridge.cpp +++ b/src/gui/Src/Bridge/Bridge.cpp @@ -840,6 +840,11 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2) emit updateTraceBrowser(); break; + case GUI_SET_MODULE_SYMBOLS: + std::vector moduleSymbols; + BridgeList::ToVector((const ListInfo*)param2, moduleSymbols, false); + symbolView->setModuleSymbols(duint(param1), moduleSymbols); + break; } return nullptr; diff --git a/src/gui/Src/Gui/SymbolView.cpp b/src/gui/Src/Gui/SymbolView.cpp index 82291fa2..2c52a20e 100644 --- a/src/gui/Src/Gui/SymbolView.cpp +++ b/src/gui/Src/Gui/SymbolView.cpp @@ -22,9 +22,13 @@ SymbolView::SymbolView(QWidget* parent) : QWidget(parent), ui(new Ui::SymbolView mMainLayout->addWidget(ui->mainSplitter); setLayout(mMainLayout); + // Create symbol table + mSymbolTable = new ZehSymbolTable(this); + // Create reference view mSearchListView = new SearchListView(true, this, true); mSearchListView->mSearchStartCol = 1; + mSearchListView->setVisible(false); // Create module list mModuleList = new SearchListView(true, this); @@ -62,7 +66,7 @@ SymbolView::SymbolView(QWidget* parent) : QWidget(parent), ui(new Ui::SymbolView // Setup list splitter ui->listSplitter->addWidget(mModuleList); - ui->listSplitter->addWidget(mSearchListView); + ui->listSplitter->addWidget(mSymbolTable); #ifdef _WIN64 // mModuleList : mSymbolList = 40 : 100 ui->listSplitter->setStretchFactor(0, 40); @@ -140,6 +144,13 @@ void SymbolView::loadWindowSettings() loadSymbolsSplitter(ui->mainSplitter, "mHSymbolsLogSplitter"); } +void SymbolView::setModuleSymbols(duint base, const std::vector & symbols) +{ + //TODO: reload actual symbol list, race conditions + GuiAddLogMessage(QString("base: %1, count: %2\n").arg(ToPtrString(base)).arg(symbols.size()).toUtf8().constData()); + mModuleSymbolMap[base] = symbols; +} + void SymbolView::setupContextMenu() { QIcon disassembler = DIcon(ArchValue("processor32.png", "processor64.png")); @@ -334,7 +345,7 @@ void SymbolView::moduleSelectionChanged(int index) Q_UNUSED(index); setUpdatesEnabled(false); - mSearchListView->mList->setRowCount(0); + /*mSearchListView->mList->setRowCount(0); for(auto index : mModuleList->mCurList->getSelection()) { QString mod = mModuleList->mCurList->getCellContent(index, 1); @@ -348,7 +359,15 @@ void SymbolView::moduleSelectionChanged(int index) if(!mSearchListView->isSearchBoxLocked()) mSearchListView->mSearchBox->setText(""); else - mSearchListView->refreshSearchList(); + mSearchListView->refreshSearchList();*/ + + QString modBase = mModuleList->mCurList->getCellContent(mModuleList->mCurList->getInitialSelection(), 0); + duint wVA; + if(!DbgFunctions()->ValFromString(modBase.toUtf8().constData(), &wVA)) + return; + mSymbolTable->mData = mModuleSymbolMap[wVA]; + mSymbolTable->setRowCount(mSymbolTable->mData.size()); + mSymbolTable->reloadData(); setUpdatesEnabled(true); } diff --git a/src/gui/Src/Gui/SymbolView.h b/src/gui/Src/Gui/SymbolView.h index 198cc91a..5a50ff28 100644 --- a/src/gui/Src/Gui/SymbolView.h +++ b/src/gui/Src/Gui/SymbolView.h @@ -3,6 +3,7 @@ #include #include "Bridge.h" +#include "ZehSymbolTable.h" class QMenu; class SearchListView; @@ -24,6 +25,8 @@ public: void saveWindowSettings(); void loadWindowSettings(); + void setModuleSymbols(duint base, const std::vector & symbols); + private slots: void updateStyle(); void addMsgToSymbolLogSlot(QString msg); @@ -69,6 +72,7 @@ private: QWidget* mSymbolPlaceHolder; SearchListView* mSearchListView; SearchListView* mModuleList; + ZehSymbolTable* mSymbolTable; QMap mModuleBaseList; QAction* mFollowSymbolAction; QAction* mFollowSymbolDumpAction; @@ -91,6 +95,8 @@ private: QAction* mLoadLib; QAction* mFreeLib; + std::map> mModuleSymbolMap; + static void cbSymbolEnum(SYMBOLINFO* symbol, void* user); }; diff --git a/src/gui/Src/Gui/ZehSymbolTable.cpp b/src/gui/Src/Gui/ZehSymbolTable.cpp new file mode 100644 index 00000000..8a182c00 --- /dev/null +++ b/src/gui/Src/Gui/ZehSymbolTable.cpp @@ -0,0 +1,66 @@ +#include "ZehSymbolTable.h" + +ZehSymbolTable::ZehSymbolTable(QWidget* parent) + : AbstractStdTable(parent) +{ + auto charwidth = getCharWidth(); + //enableMultiSelection(true); //TODO + addColumnAt(charwidth * 2 * sizeof(dsint) + 8, tr("Address"), true); + addColumnAt(charwidth * 6 + 8, tr("Type"), true); + addColumnAt(charwidth * 80, tr("Symbol"), true); + addColumnAt(2000, tr("Symbol (undecorated)"), true); + //loadColumnFromConfig("Symbol"); //TODO +} + +QString ZehSymbolTable::getCellContent(int r, int c) +{ + if(!isValidIndex(r, c)) + return QString(); + SYMBOLINFO info = {0}; + DbgGetSymbolInfo(mData.at(r), &info); + switch(c) + { + case ColAddr: + return ToPtrString(info.addr); + case ColType: + return info.isImported ? tr("Import") : tr("Export"); + case ColDecorated: + return info.decoratedSymbol; + case ColUndecorated: + return info.undecoratedSymbol; + default: + return QString(); + } +} + +bool ZehSymbolTable::isValidIndex(int r, int c) +{ + return r >= 0 && r < mData.size() && c >= 0 && c <= ColUndecorated; +} + +void ZehSymbolTable::sortRows(int column, bool ascending) +{ + std::stable_sort(mData.begin(), mData.end(), [column, ascending](void* a, void* b) + { + SYMBOLINFO ainfo, binfo; + DbgGetSymbolInfo(a, &ainfo); + DbgGetSymbolInfo(b, &binfo); + bool less; + switch(column) + { + case ColAddr: + less = ainfo.addr < binfo.addr; + break; + case ColType: + less = ainfo.isImported < binfo.isImported; + break; + case ColDecorated: + less = strcmp(ainfo.decoratedSymbol, binfo.decoratedSymbol) < 0; + break; + case ColUndecorated: + less = strcmp(ainfo.undecoratedSymbol, binfo.undecoratedSymbol) < 0; + break; + } + return ascending ? less : !less; + }); +} diff --git a/src/gui/Src/Gui/ZehSymbolTable.h b/src/gui/Src/Gui/ZehSymbolTable.h new file mode 100644 index 00000000..cce39e55 --- /dev/null +++ b/src/gui/Src/Gui/ZehSymbolTable.h @@ -0,0 +1,27 @@ +#pragma once + +#include "AbstractStdTable.h" + +class ZehSymbolTable : public AbstractStdTable +{ + Q_OBJECT +public: + ZehSymbolTable(QWidget* parent); + + QString getCellContent(int r, int c) override; + bool isValidIndex(int r, int c) override; + void sortRows(int column, bool ascending) override; + + friend class SymbolView; + +private: + std::vector mData; + + enum + { + ColAddr, + ColType, + ColDecorated, + ColUndecorated + }; +}; diff --git a/src/gui/x64dbg.pro b/src/gui/x64dbg.pro index 279d30c2..321d4a44 100644 --- a/src/gui/x64dbg.pro +++ b/src/gui/x64dbg.pro @@ -186,7 +186,8 @@ SOURCES += \ Src/Tracer/TraceFileReader.cpp \ Src/Tracer/TraceFileSearch.cpp \ Src/Gui/MultiItemsSelectWindow.cpp \ - Src/BasicView/AbstractStdTable.cpp + Src/BasicView/AbstractStdTable.cpp \ + Src/Gui/ZehSymbolTable.cpp HEADERS += \ @@ -308,7 +309,8 @@ HEADERS += \ Src/Tracer/TraceFileReaderInternal.h \ Src/Tracer/TraceFileSearch.h \ Src/Gui/MultiItemsSelectWindow.h \ - Src/BasicView/AbstractStdTable.h + Src/BasicView/AbstractStdTable.h \ + Src/Gui/ZehSymbolTable.h FORMS += \ diff --git a/src/x64dbg_translations.pro b/src/x64dbg_translations.pro index e6dba831..8caa1dc8 100644 --- a/src/x64dbg_translations.pro +++ b/src/x64dbg_translations.pro @@ -225,7 +225,8 @@ SOURCES += \ gui/Src/Tracer/TraceFileReader.cpp \ gui/Src/Tracer/TraceFileSearch.cpp \ gui/Src/Gui/MultiItemsSelectWindow.cpp \ - gui/Src/BasicView/AbstractStdTable.cpp + gui/Src/BasicView/AbstractStdTable.cpp \ + gui/Src/Gui/ZehSymbolTable.cpp HEADERS += \ gui/Src/Exports.h \ @@ -462,7 +463,8 @@ HEADERS += \ gui/Src/Tracer/TraceFileReaderInternal.h \ gui/Src/Tracer/TraceFileSearch.h \ gui/Src/Gui/MultiItemsSelectWindow.h \ - gui/Src/BasicView/AbstractStdTable.h + gui/Src/BasicView/AbstractStdTable.h \ + gui/Src/Gui/ZehSymbolTable.h FORMS += \ gui/Src/Gui/AppearanceDialog.ui \