From bc4149b86603912ebb7a243c20181a315cbff702 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Fri, 26 Dec 2014 13:04:08 +0100 Subject: [PATCH 01/16] GUI: fixed 'follow in disassembler' and 'follow in dump' not possible with EDX/RDX --- x64_dbg_gui/Project/Src/Gui/RegistersView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x64_dbg_gui/Project/Src/Gui/RegistersView.cpp b/x64_dbg_gui/Project/Src/Gui/RegistersView.cpp index d8ea8f61..d00d39f5 100644 --- a/x64_dbg_gui/Project/Src/Gui/RegistersView.cpp +++ b/x64_dbg_gui/Project/Src/Gui/RegistersView.cpp @@ -465,7 +465,7 @@ RegistersView::RegistersView(QWidget* parent) : QScrollArea(parent), mVScrollOff mUINTDISPLAY.insert(CDX); mLABELDISPLAY.insert(CDX); mMODIFYDISPLAY.insert(CDX); - mCANSTOREADDRESS.insert(CCX); + mCANSTOREADDRESS.insert(CDX); mSETONEZEROTOGGLE.insert(CBP); mINCREMENTDECREMET.insert(CBP); From 842469eff40a21a9f6ec4b5a19bd67a22657e2fb Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Fri, 26 Dec 2014 14:40:49 +0100 Subject: [PATCH 02/16] DBG: automatic comments will have a '\1' character as prefix. --- x64_dbg_dbg/_exports.cpp | 8 +++++--- x64_dbg_dbg/addrinfo.cpp | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/x64_dbg_dbg/_exports.cpp b/x64_dbg_dbg/_exports.cpp index 7f723b75..4ae7baff 100644 --- a/x64_dbg_dbg/_exports.cpp +++ b/x64_dbg_dbg/_exports.cpp @@ -163,7 +163,7 @@ extern "C" DLL_EXPORT bool _dbg_addrinfoget(duint addr, SEGMENTREG segment, ADDR len--; if(len) len++; - sprintf(addrinfo->comment, "%s:%u", filename + len, line.LineNumber); + sprintf_s(addrinfo->comment, "\1%s:%u", filename + len, line.LineNumber); retval = true; } else if(!bOnlyCipAutoComments || addr == GetContextDataEx(hActiveThread, UE_CIP)) //no line number @@ -273,8 +273,10 @@ extern "C" DLL_EXPORT bool _dbg_addrinfoget(duint addr, SEGMENTREG segment, ADDR retval = true; } } - comment.resize(MAX_COMMENT_SIZE - 1); - strcpy_s(addrinfo->comment, comment.c_str()); + comment.resize(MAX_COMMENT_SIZE - 2); + String fullComment = "\1"; + fullComment += comment; + strcpy_s(addrinfo->comment, fullComment.c_str()); } } } diff --git a/x64_dbg_dbg/addrinfo.cpp b/x64_dbg_dbg/addrinfo.cpp index 186b444b..62ce22a3 100644 --- a/x64_dbg_dbg/addrinfo.cpp +++ b/x64_dbg_dbg/addrinfo.cpp @@ -380,7 +380,7 @@ bool apienumexports(uint base, EXPORTENUMCALLBACK cbEnum) ///comment functions bool commentset(uint addr, const char* text, bool manual) { - if(!DbgIsDebugging() or !memisvalidreadptr(fdProcessInfo->hProcess, addr) or !text or strlen(text) >= MAX_COMMENT_SIZE - 1) + if(!DbgIsDebugging() or !memisvalidreadptr(fdProcessInfo->hProcess, addr) or !text or text[0] == '\1' or strlen(text) >= MAX_COMMENT_SIZE - 1) return false; if(!*text) //NOTE: delete when there is no text { From 0bccbd0c0dbce8551949fb2cd9979955d52168bc Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Fri, 26 Dec 2014 14:43:20 +0100 Subject: [PATCH 03/16] GUI: resolved issue #229 (automatic comments have a different color) --- .../Project/Src/BasicView/Disassembly.cpp | 23 +++++++++++++++---- .../Project/Src/Gui/AppearanceDialog.cpp | 1 + .../Project/Src/Gui/BreakpointsView.cpp | 21 ++++++++++++++--- .../Project/Src/Gui/CPUDisassembly.cpp | 14 +++++++++-- .../Project/Src/Utils/Configuration.cpp | 2 ++ 5 files changed, 52 insertions(+), 9 deletions(-) diff --git a/x64_dbg_gui/Project/Src/BasicView/Disassembly.cpp b/x64_dbg_gui/Project/Src/BasicView/Disassembly.cpp index 8be1ef08..16570069 100644 --- a/x64_dbg_gui/Project/Src/BasicView/Disassembly.cpp +++ b/x64_dbg_gui/Project/Src/BasicView/Disassembly.cpp @@ -380,13 +380,28 @@ QString Disassembly::paintContent(QPainter* painter, int_t rowBase, int rowOffse char comment[MAX_COMMENT_SIZE] = ""; if(DbgGetCommentAt(rvaToVa(mInstBuffer.at(rowOffset).rva), comment)) { - painter->setPen(ConfigColor("DisassemblyCommentColor")); - int width = getCharWidth() * QString(comment).length() + 4; + QString commentText; + QColor penColor; + QColor backgroundColor; + if(comment[0] == '\1') //automatic comment + { + penColor = ConfigColor("DisassemblyAutoCommentColor"); + backgroundColor = ConfigColor("DisassemblyAutoCommentBackgroundColor"); + commentText = QString(comment + 1); + } + else //user comment + { + penColor = ConfigColor("DisassemblyCommentColor"); + backgroundColor = ConfigColor("DisassemblyCommentBackgroundColor"); + commentText = comment; + } + painter->setPen(penColor); + int width = getCharWidth() * commentText.length() + 4; if(width > w) width = w; if(width) - painter->fillRect(QRect(x + 2, y, width, h), QBrush(ConfigColor("DisassemblyCommentBackgroundColor"))); //fill bookmark color - painter->drawText(QRect(x + 4, y , w - 4 , h), Qt::AlignVCenter | Qt::AlignLeft, QString(comment)); + painter->fillRect(QRect(x + 2, y, width, h), QBrush(backgroundColor)); //fill comment color + painter->drawText(QRect(x + 4, y , w - 4 , h), Qt::AlignVCenter | Qt::AlignLeft, commentText); } } break; diff --git a/x64_dbg_gui/Project/Src/Gui/AppearanceDialog.cpp b/x64_dbg_gui/Project/Src/Gui/AppearanceDialog.cpp index 6ea0e2fb..5f5a9823 100644 --- a/x64_dbg_gui/Project/Src/Gui/AppearanceDialog.cpp +++ b/x64_dbg_gui/Project/Src/Gui/AppearanceDialog.cpp @@ -428,6 +428,7 @@ void AppearanceDialog::colorInfoListInit() colorInfoListAppend("Hardware Breakpoints", "DisassemblyHardwareBreakpointColor", "DisassemblyHardwareBreakpointBackgroundColor"); colorInfoListAppend("Bookmarks", "DisassemblyBookmarkColor", "DisassemblyBookmarkBackgroundColor"); colorInfoListAppend("Comments", "DisassemblyCommentColor", "DisassemblyCommentBackgroundColor"); + colorInfoListAppend("Automatic Comments", "DisassemblyAutoCommentColor", "DisassemblyAutoCommentBackgroundColor"); colorInfoListAppend("Labels", "DisassemblyLabelColor", "DisassemblyLabelBackgroundColor"); colorInfoListAppend("Addresses", "DisassemblyAddressColor", "DisassemblyAddressBackgroundColor"); colorInfoListAppend("Selected Addresses", "DisassemblySelectedAddressColor", "DisassemblySelectedAddressBackgroundColor"); diff --git a/x64_dbg_gui/Project/Src/Gui/BreakpointsView.cpp b/x64_dbg_gui/Project/Src/Gui/BreakpointsView.cpp index 48d70b09..74266e41 100644 --- a/x64_dbg_gui/Project/Src/Gui/BreakpointsView.cpp +++ b/x64_dbg_gui/Project/Src/Gui/BreakpointsView.cpp @@ -97,7 +97,12 @@ void BreakpointsView::reloadData() char comment[MAX_COMMENT_SIZE] = ""; if(DbgGetCommentAt(wBPList.bp[wI].addr, comment)) - mHardBPTable->setCellContent(wI, 4, comment); + { + if(comment[0] == '\1') //automatic comment + mHardBPTable->setCellContent(wI, 4, QString(comment + 1)); + else + mHardBPTable->setCellContent(wI, 4, comment); + } } mHardBPTable->reloadData(); if(wBPList.count) @@ -129,7 +134,12 @@ void BreakpointsView::reloadData() char comment[MAX_COMMENT_SIZE] = ""; if(DbgGetCommentAt(wBPList.bp[wI].addr, comment)) - mSoftBPTable->setCellContent(wI, 4, comment); + { + if(comment[0] == '\1') //automatic comment + mSoftBPTable->setCellContent(wI, 4, QString(comment + 1)); + else + mSoftBPTable->setCellContent(wI, 4, comment); + } } mSoftBPTable->reloadData(); if(wBPList.count) @@ -161,7 +171,12 @@ void BreakpointsView::reloadData() char comment[MAX_COMMENT_SIZE] = ""; if(DbgGetCommentAt(wBPList.bp[wI].addr, comment)) - mMemBPTable->setCellContent(wI, 4, comment); + { + if(comment[0] == '\1') //automatic comment + mMemBPTable->setCellContent(wI, 4, QString(comment + 1)); + else + mMemBPTable->setCellContent(wI, 4, comment); + } } mMemBPTable->reloadData(); if(wBPList.count) diff --git a/x64_dbg_gui/Project/Src/Gui/CPUDisassembly.cpp b/x64_dbg_gui/Project/Src/Gui/CPUDisassembly.cpp index 072fa532..2503a4d2 100644 --- a/x64_dbg_gui/Project/Src/Gui/CPUDisassembly.cpp +++ b/x64_dbg_gui/Project/Src/Gui/CPUDisassembly.cpp @@ -708,7 +708,12 @@ void CPUDisassembly::setComment() QString addr_text = QString("%1").arg(wVA, sizeof(int_t) * 2, 16, QChar('0')).toUpper(); char comment_text[MAX_COMMENT_SIZE] = ""; if(DbgGetCommentAt((duint)wVA, comment_text)) - mLineEdit.setText(QString(comment_text)); + { + if(comment_text[0] == '\1') //automatic comment + mLineEdit.setText(QString(comment_text + 1)); + else + mLineEdit.setText(QString(comment_text)); + } mLineEdit.setWindowTitle("Add comment at " + addr_text); if(mLineEdit.exec() != QDialog::Accepted) return; @@ -1160,7 +1165,12 @@ void CPUDisassembly::copySelection(bool copyBytes) char comment[MAX_COMMENT_SIZE] = ""; QString fullComment; if(DbgGetCommentAt(cur_addr, comment)) - fullComment = " ;" + QString(comment); + { + if(comment[0] == '\1') //automatic comment + fullComment = " ;" + QString(comment + 1); + else + fullComment = " ;" + QString(comment); + } clipboard += address.leftJustified(addressLen, QChar(' '), true); if(copyBytes) clipboard += " | " + bytes.leftJustified(bytesLen, QChar(' '), true); diff --git a/x64_dbg_gui/Project/Src/Utils/Configuration.cpp b/x64_dbg_gui/Project/Src/Utils/Configuration.cpp index 92d51dab..cd55f46e 100644 --- a/x64_dbg_gui/Project/Src/Utils/Configuration.cpp +++ b/x64_dbg_gui/Project/Src/Utils/Configuration.cpp @@ -39,6 +39,8 @@ Configuration::Configuration() : QObject() defaultColors.insert("DisassemblyModifiedBytesColor", QColor("#FF0000")); defaultColors.insert("DisassemblyCommentColor", QColor("#000000")); defaultColors.insert("DisassemblyCommentBackgroundColor", Qt::transparent); + defaultColors.insert("DisassemblyAutoCommentColor", QColor("#808080")); + defaultColors.insert("DisassemblyAutoCommentBackgroundColor", Qt::transparent); defaultColors.insert("SideBarCipLabelColor", QColor("#FFFFFF")); defaultColors.insert("SideBarCipLabelBackgroundColor", QColor("#4040FF")); From ce2f1405377d84c0185742b002ad3209fc59d790 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Fri, 26 Dec 2014 14:49:45 +0100 Subject: [PATCH 04/16] GUI: resolved issue #228 (double click in dump or stack starts editing data) --- x64_dbg_gui/Project/Src/Gui/CPUDump.cpp | 5 ++++- x64_dbg_gui/Project/Src/Gui/CPUStack.cpp | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/x64_dbg_gui/Project/Src/Gui/CPUDump.cpp b/x64_dbg_gui/Project/Src/Gui/CPUDump.cpp index 67021765..58c8322d 100644 --- a/x64_dbg_gui/Project/Src/Gui/CPUDump.cpp +++ b/x64_dbg_gui/Project/Src/Gui/CPUDump.cpp @@ -521,7 +521,10 @@ void CPUDump::mouseDoubleClickEvent(QMouseEvent* event) break; default: - break; + { + binaryEditSlot(); + } + break; } } diff --git a/x64_dbg_gui/Project/Src/Gui/CPUStack.cpp b/x64_dbg_gui/Project/Src/Gui/CPUStack.cpp index 519a0825..059646cf 100644 --- a/x64_dbg_gui/Project/Src/Gui/CPUStack.cpp +++ b/x64_dbg_gui/Project/Src/Gui/CPUStack.cpp @@ -358,7 +358,10 @@ void CPUStack::mouseDoubleClickEvent(QMouseEvent* event) break; default: - break; + { + modifySlot(); + } + break; } } From ed5fbad687e4f4bf1720b21f93c7deca1d3e6277 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Mon, 29 Dec 2014 00:41:22 +0100 Subject: [PATCH 05/16] DBG: allow accessing the entry point of a module with ":entry" --- help/Input.htm | 6 ++++++ x64_dbg_dbg/value.cpp | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/help/Input.htm b/help/Input.htm index 3a41472f..888495c0 100644 --- a/help/Input.htm +++ b/help/Input.htm @@ -64,6 +64,12 @@ you can write "[module]:$[rva]". If you want to convert a file offset to a VA you can use "[module]:#[offset]". When "[module]" is an empty string (":0" for example), the module that is currently selected in the CPU will be used.

+

Module Entry Points + + : To +access a module entry point you can write "[module]:entry", "[module]:oep" or "[module]:ep". Notice that when +there are exports with the names "entry", "oep" or "ep" the address of these will be +returned instead.

labels/symbols: user-defined labels and symbols are a valid expressions.

Input for arguments can always be done in any of diff --git a/x64_dbg_dbg/value.cpp b/x64_dbg_dbg/value.cpp index 83fc6559..82ab63c3 100644 --- a/x64_dbg_dbg/value.cpp +++ b/x64_dbg_dbg/value.cpp @@ -1213,8 +1213,10 @@ bool valapifromstring(const char* name, uint* value, int* value_size, bool print uint addr = (uint)GetProcAddress(mod, apiname); if(!addr) //not found { - if(!_stricmp(apiname, "base") or !_stricmp(apiname, "imagebase") or !_stricmp(apiname, "header")) + if(scmp(apiname, "base") or scmp(apiname, "imagebase") or scmp(apiname, "header")) //get loaded base addr = modbase; + else if(scmp(apiname, "entry") or scmp(apiname, "oep") or scmp(apiname, "ep")) //get entry point + addr = modbase + GetPE32DataW(szModName, 0, UE_OEP); else if(*apiname == '$') //RVA { uint rva; @@ -1233,7 +1235,7 @@ bool valapifromstring(const char* name, uint* value, int* value_size, bool print if(valfromstring(apiname, &ordinal)) { addr = (uint)GetProcAddress(mod, (LPCSTR)(ordinal & 0xFFFF)); - if(!addr and !ordinal) + if(!addr and !ordinal) //support for getting the image base using :0 addr = modbase; } } From 7deb13966ebd3c3133a78cbb7c2112e9598cbe4a Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Mon, 29 Dec 2014 00:58:59 +0100 Subject: [PATCH 06/16] DBG: added possibility for '?' as delimiter. this ignores exports (useful if there are exports called "entry" or "imagebase") --- help/Input.htm | 35 +++++++++++++++++++++++------------ x64_dbg_dbg/value.cpp | 12 +++++++++--- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/help/Input.htm b/help/Input.htm index 888495c0..677d0b62 100644 --- a/help/Input.htm +++ b/help/Input.htm @@ -49,27 +49,38 @@ numbers are interpreted as hex by default. If you want to be sure, you can use the "x" prefix or the "0x" prefix. Decimal numbers can be used by prefixing the number with a "." (.123=7B).

basic calculations: See "Calculations" for more information.

-

DLL exports: Type -'GetProcAddress' and it will automatically be resolved to the actual address of -the function. To explicitly define from which module -to load the API, use: "[module].dll:[api]" or "[module]:[api]". In a similar -way you can resolve ordinals, try "[module]:[ordinal]". Another macro allows you to get the -loaded base of a module. Try "[module]:0", -"[module]:base", "[module]:imagebase" or "[module]:header". When "[module]" is an empty string (":0" for example), the +

DLL exports + : Type 'GetProcAddress' and it will automatically be +resolved to the actual address of the function. +To explicitly define from which module to load the API, use: +"[module].dll:[api]" or "[module]:[api]". In a similar way you can resolve ordinals, try "[module]:[ordinal]". Another +macro allows you to get the loaded +base of a module. When "[module]" is an empty string (":GetProcAddress" for example), the module that is currently selected in the CPU will be used.

+

Loaded Module Bases + + + + : If you want to access the loaded module base, +you can write: "[module]:0", "[module]:base", "[module]:imagebase" or +"[module]:header". You can also use '?' as a delimiter instead of ':'. This is +useful if the module contains an export called "imagebase" for +example.

RVA/File Offset: If you want to access a module RVA you can either write "[module]:0+[rva]" or you can write "[module]:$[rva]". If you want to convert a file offset to a VA you can use "[module]:#[offset]". When "[module]" is an empty string (":0" for example), the module that is currently selected in the CPU will be used.

-

Module Entry Points +

Module Entry Points : To access a module entry point you can write "[module]:entry", +"[module]:oep" or "[module]:ep". Notice that when there are exports with the +names "entry", - : To -access a module entry point you can write "[module]:entry", "[module]:oep" or "[module]:ep". Notice that when -there are exports with the names "entry", "oep" or "ep" the address of these will be -returned instead.

+ "oep" or +"ep" the address of these will be returned instead. You can also use '?' as +a delimiter instead of ':'. This is useful if the module contains an export called "entry" +for example.

labels/symbols: user-defined labels and symbols are a valid expressions.

Input for arguments can always be done in any of diff --git a/x64_dbg_dbg/value.cpp b/x64_dbg_dbg/value.cpp index 82ab63c3..1cd5d425 100644 --- a/x64_dbg_dbg/value.cpp +++ b/x64_dbg_dbg/value.cpp @@ -1169,7 +1169,13 @@ bool valapifromstring(const char* name, uint* value, int* value_size, bool print if(!value or !DbgIsDebugging()) return false; //explicit API handling - const char* apiname = strstr(name, ":"); + const char* apiname = strstr(name, ":"); //the ':' character cannot be in a path: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#naming_conventions + bool noexports = false; + if(!apiname) + { + apiname = strstr(name, "?"); //the '?' character cannot be in a path either + noexports = true; + } if(apiname) { char modname[MAX_MODULE_SIZE] = ""; @@ -1210,7 +1216,7 @@ bool valapifromstring(const char* name, uint* value, int* value_size, bool print } else { - uint addr = (uint)GetProcAddress(mod, apiname); + uint addr = noexports ? 0 : (uint)GetProcAddress(mod, apiname); if(!addr) //not found { if(scmp(apiname, "base") or scmp(apiname, "imagebase") or scmp(apiname, "header")) //get loaded base @@ -1234,7 +1240,7 @@ bool valapifromstring(const char* name, uint* value, int* value_size, bool print uint ordinal; if(valfromstring(apiname, &ordinal)) { - addr = (uint)GetProcAddress(mod, (LPCSTR)(ordinal & 0xFFFF)); + addr = noexports ? 0 : (uint)GetProcAddress(mod, (LPCSTR)(ordinal & 0xFFFF)); if(!addr and !ordinal) //support for getting the image base using :0 addr = modbase; } From 50e3388de10ece2ad9ffb7e67f55857dd907d29c Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Mon, 29 Dec 2014 00:59:57 +0100 Subject: [PATCH 07/16] GUI: added "Follow Entry Point in Disassembler" option in Symbols view --- x64_dbg_gui/Project/Src/Gui/SymbolView.cpp | 10 ++++++++++ x64_dbg_gui/Project/Src/Gui/SymbolView.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/x64_dbg_gui/Project/Src/Gui/SymbolView.cpp b/x64_dbg_gui/Project/Src/Gui/SymbolView.cpp index d279ca7c..e2e31985 100644 --- a/x64_dbg_gui/Project/Src/Gui/SymbolView.cpp +++ b/x64_dbg_gui/Project/Src/Gui/SymbolView.cpp @@ -111,6 +111,9 @@ void SymbolView::setupContextMenu() mFollowModuleAction->setShortcut(QKeySequence("enter")); connect(mFollowModuleAction, SIGNAL(triggered()), this, SLOT(moduleFollow())); + mFollowModuleEntryAction = new QAction("Follow &Entry Point in Disassembler", this); + connect(mFollowModuleEntryAction, SIGNAL(triggered()), this, SLOT(moduleEntryFollow())); + mDownloadSymbolsAction = new QAction("&Download Symbols for This Module", this); connect(mDownloadSymbolsAction, SIGNAL(triggered()), this, SLOT(moduleDownloadSymbols())); @@ -231,6 +234,7 @@ void SymbolView::moduleContextMenu(const QPoint & pos) return; QMenu* wMenu = new QMenu(this); //create context menu wMenu->addAction(mFollowModuleAction); + wMenu->addAction(mFollowModuleEntryAction); wMenu->addAction(mDownloadSymbolsAction); wMenu->addAction(mDownloadAllSymbolsAction); QMenu wCopyMenu("&Copy", this); @@ -249,6 +253,12 @@ void SymbolView::moduleFollow() emit showCpu(); } +void SymbolView::moduleEntryFollow() +{ + DbgCmdExecDirect(QString("disasm " + mModuleList->getCellContent(mModuleList->getInitialSelection(), 1) + "?entry").toUtf8().constData()); + emit showCpu(); +} + void SymbolView::moduleDownloadSymbols() { DbgCmdExec(QString("symdownload " + mModuleList->getCellContent(mModuleList->getInitialSelection(), 1)).toUtf8().constData()); diff --git a/x64_dbg_gui/Project/Src/Gui/SymbolView.h b/x64_dbg_gui/Project/Src/Gui/SymbolView.h index af1134e0..92f5d206 100644 --- a/x64_dbg_gui/Project/Src/Gui/SymbolView.h +++ b/x64_dbg_gui/Project/Src/Gui/SymbolView.h @@ -30,6 +30,7 @@ private slots: void symbolRefreshCurrent(); void moduleContextMenu(const QPoint & pos); void moduleFollow(); + void moduleEntryFollow(); void moduleDownloadSymbols(); void moduleDownloadAllSymbols(); void toggleBreakpoint(); @@ -52,6 +53,7 @@ private: QAction* mToggleBreakpoint; QAction* mToggleBookmark; QAction* mFollowModuleAction; + QAction* mFollowModuleEntryAction; QAction* mDownloadSymbolsAction; QAction* mDownloadAllSymbolsAction; From 3199025d7bc14c449142691e63f1edbc650d5d8e Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Mon, 29 Dec 2014 01:29:57 +0100 Subject: [PATCH 08/16] DBG: fixed a bug in valapifromstring (the correction for the loaded base in the debuggee was bad) --- x64_dbg_dbg/value.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/x64_dbg_dbg/value.cpp b/x64_dbg_dbg/value.cpp index 1cd5d425..ed5a1754 100644 --- a/x64_dbg_dbg/value.cpp +++ b/x64_dbg_dbg/value.cpp @@ -1217,7 +1217,9 @@ bool valapifromstring(const char* name, uint* value, int* value_size, bool print else { uint addr = noexports ? 0 : (uint)GetProcAddress(mod, apiname); - if(!addr) //not found + if(addr) //found exported function + addr = modbase + (addr - (uint)mod); //correct for loaded base + else //not found { if(scmp(apiname, "base") or scmp(apiname, "imagebase") or scmp(apiname, "header")) //get loaded base addr = modbase; @@ -1241,7 +1243,9 @@ bool valapifromstring(const char* name, uint* value, int* value_size, bool print if(valfromstring(apiname, &ordinal)) { addr = noexports ? 0 : (uint)GetProcAddress(mod, (LPCSTR)(ordinal & 0xFFFF)); - if(!addr and !ordinal) //support for getting the image base using :0 + if(addr) //found exported function + addr = modbase + (addr - (uint)mod); //correct for loaded base + else if(!ordinal) //support for getting the image base using :0 addr = modbase; } } @@ -1253,12 +1257,7 @@ bool valapifromstring(const char* name, uint* value, int* value_size, bool print *value_size = sizeof(uint); if(hexonly) *hexonly = true; - uint rva; - if(addr == modbase) - rva = 0; - else - rva = addr - (uint)mod; - *value = modbase + rva; + *value = addr; return true; } } From a30fecb90b8641f499d30e0e50aad9016819cfe1 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Mon, 29 Dec 2014 01:30:33 +0100 Subject: [PATCH 09/16] GUI: added an option to copy the file path of a module --- x64_dbg_gui/Project/Src/Gui/SymbolView.cpp | 15 +++++++++++++++ x64_dbg_gui/Project/Src/Gui/SymbolView.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/x64_dbg_gui/Project/Src/Gui/SymbolView.cpp b/x64_dbg_gui/Project/Src/Gui/SymbolView.cpp index e2e31985..8e96cb3e 100644 --- a/x64_dbg_gui/Project/Src/Gui/SymbolView.cpp +++ b/x64_dbg_gui/Project/Src/Gui/SymbolView.cpp @@ -120,6 +120,9 @@ void SymbolView::setupContextMenu() mDownloadAllSymbolsAction = new QAction("Download Symbols for &All Modules", this); connect(mDownloadAllSymbolsAction, SIGNAL(triggered()), this, SLOT(moduleDownloadAllSymbols())); + mCopyPathAction = new QAction("Copy File &Path", this); + connect(mCopyPathAction, SIGNAL(triggered()), this, SLOT(moduleCopyPath())); + //Shortcuts refreshShortcutsSlot(); connect(Config(), SIGNAL(shortcutsUpdated()), this, SLOT(refreshShortcutsSlot())); @@ -237,6 +240,10 @@ void SymbolView::moduleContextMenu(const QPoint & pos) wMenu->addAction(mFollowModuleEntryAction); wMenu->addAction(mDownloadSymbolsAction); wMenu->addAction(mDownloadAllSymbolsAction); + int_t modbase = DbgValFromString(mModuleList->getCellContent(mModuleList->getInitialSelection(), 0).toUtf8().constData()); + char szModPath[MAX_PATH] = ""; + if(DbgFunctions()->ModPathFromAddr(modbase, szModPath, _countof(szModPath))) + wMenu->addAction(mCopyPathAction); QMenu wCopyMenu("&Copy", this); mModuleList->setupCopyMenu(&wCopyMenu); if(wCopyMenu.actions().length()) @@ -259,6 +266,14 @@ void SymbolView::moduleEntryFollow() emit showCpu(); } +void SymbolView::moduleCopyPath() +{ + int_t modbase = DbgValFromString(mModuleList->getCellContent(mModuleList->getInitialSelection(), 0).toUtf8().constData()); + char szModPath[MAX_PATH] = ""; + if(DbgFunctions()->ModPathFromAddr(modbase, szModPath, _countof(szModPath))) + Bridge::CopyToClipboard(szModPath); +} + void SymbolView::moduleDownloadSymbols() { DbgCmdExec(QString("symdownload " + mModuleList->getCellContent(mModuleList->getInitialSelection(), 1)).toUtf8().constData()); diff --git a/x64_dbg_gui/Project/Src/Gui/SymbolView.h b/x64_dbg_gui/Project/Src/Gui/SymbolView.h index 92f5d206..b421b14a 100644 --- a/x64_dbg_gui/Project/Src/Gui/SymbolView.h +++ b/x64_dbg_gui/Project/Src/Gui/SymbolView.h @@ -33,6 +33,7 @@ private slots: void moduleEntryFollow(); void moduleDownloadSymbols(); void moduleDownloadAllSymbols(); + void moduleCopyPath(); void toggleBreakpoint(); void toggleBookmark(); void refreshShortcutsSlot(); @@ -56,6 +57,7 @@ private: QAction* mFollowModuleEntryAction; QAction* mDownloadSymbolsAction; QAction* mDownloadAllSymbolsAction; + QAction* mCopyPathAction; static void cbSymbolEnum(SYMBOLINFO* symbol, void* user); }; From c17419fc98cbe80ebd391f1f463c63dce2258ce2 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Mon, 29 Dec 2014 02:02:34 +0100 Subject: [PATCH 10/16] DBG: more fixes in valapifromstring (this function is getting really complex and confusing now) --- help/Input.htm | 50 +++++++++---------- x64_dbg_dbg/value.cpp | 110 ++++++++++++++++++++++-------------------- 2 files changed, 82 insertions(+), 78 deletions(-) diff --git a/help/Input.htm b/help/Input.htm index 677d0b62..e1fdfb54 100644 --- a/help/Input.htm +++ b/help/Input.htm @@ -49,38 +49,36 @@ numbers are interpreted as hex by default. If you want to be sure, you can use the "x" prefix or the "0x" prefix. Decimal numbers can be used by prefixing the number with a "." (.123=7B).

basic calculations: See "Calculations" for more information.

-

DLL exports - : Type 'GetProcAddress' and it will automatically be +

Module Data:

+
    +
  1. +
    DLL exports: + Type 'GetProcAddress' and it will automatically be resolved to the actual address of the function. To explicitly define from which module to load the API, use: "[module].dll:[api]" or "[module]:[api]". In a similar way you can resolve ordinals, try "[module]:[ordinal]". Another macro allows you to get the loaded base of a module. When "[module]" is an empty string (":GetProcAddress" for example), the module that is currently selected in the CPU will be -used.

    -

    Loaded Module Bases - - - - : If you want to access the loaded module base, -you can write: "[module]:0", "[module]:base", "[module]:imagebase" or -"[module]:header". You can also use '?' as a delimiter instead of ':'. This is -useful if the module contains an export called "imagebase" for -example.

    -

    RVA/File Offset: -If you want to access a module RVA you can either write "[module]:0+[rva]" or -you can write "[module]:$[rva]". If you want -to convert a file offset to a VA you can use "[module]:#[offset]". When "[module]" is -an empty string (":0" for example), the module that is currently selected in the CPU will -be used.

    -

    Module Entry Points : To access a module entry point you can write "[module]:entry", -"[module]:oep" or "[module]:ep". Notice that when there are exports with the -names "entry", - - "oep" or -"ep" the address of these will be returned instead. You can also use '?' as -a delimiter instead of ':'. This is useful if the module contains an export called "entry" -for example.

    +used.
    +
  2. Loaded Module Bases: + If you want to access the loaded module base, you can write: "[module]:0", + "[module]:base", "[module]:imagebase" or "[module]:header". +
  3. RVA/File Offset: If you + want to access a module RVA you can either write "[module]:0+[rva]" or you can + write "[module]:$[rva]". If you want to convert a file offset to a VA you can + use "[module]:#[offset]". When "[module]" is an empty string (":0" for + example), the module that is currently selected in the CPU will be used. +
  4. Module Entry Points: To + access a module entry point you can write "[module]:entry", "[module]:oep" or + "[module]:ep". Notice that when there are exports with the names "entry", + "oep" or "ep" the address of these will be returned + instead.

    Notice: Instead of the ':' delimiter you can + also use a '.' If you need to query module information such as + "[module]:imagebase" or "[module]":entry" you are adviced to + use a '?' as delimiter instead ("[module]?entry"). The '?' does + checking for named exports later, so it will still work when there is an + export called "entry" in the module.

labels/symbols: user-defined labels and symbols are a valid expressions.

Input for arguments can always be done in any of diff --git a/x64_dbg_dbg/value.cpp b/x64_dbg_dbg/value.cpp index ed5a1754..918d454f 100644 --- a/x64_dbg_dbg/value.cpp +++ b/x64_dbg_dbg/value.cpp @@ -1169,12 +1169,16 @@ bool valapifromstring(const char* name, uint* value, int* value_size, bool print if(!value or !DbgIsDebugging()) return false; //explicit API handling - const char* apiname = strstr(name, ":"); //the ':' character cannot be in a path: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#naming_conventions + const char* apiname = strchr(name, ':'); //the ':' character cannot be in a path: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#naming_conventions bool noexports = false; - if(!apiname) + if(!apiname) //not found { - apiname = strstr(name, "?"); //the '?' character cannot be in a path either - noexports = true; + apiname = strrchr(name, '.'); //kernel32.GetProcAddress support + if(!apiname) //not found + { + apiname = strchr(name, '?'); //the '?' character cannot be in a path either + noexports = true; + } } if(apiname) { @@ -1204,45 +1208,49 @@ bool valapifromstring(const char* name, uint* value, int* value_size, bool print } else { - wchar_t* szBaseName = wcschr(szModName, L'\\'); - if(szBaseName) + HMODULE mod = LoadLibraryExW(szModName, 0, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE); + if(!mod) { - szBaseName++; - HMODULE mod = LoadLibraryExW(szModName, 0, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE); - if(!mod) + if(!silent) + dprintf("unable to load library %s\n", szModName); + } + else + { + uint addr = noexports ? 0 : (uint)GetProcAddress(mod, apiname); + if(addr) //found exported function + addr = modbase + (addr - (uint)mod); //correct for loaded base + else //not found { - if(!silent) - dprintf("unable to load library %s\n", szBaseName); - } - else - { - uint addr = noexports ? 0 : (uint)GetProcAddress(mod, apiname); - if(addr) //found exported function - addr = modbase + (addr - (uint)mod); //correct for loaded base - else //not found + if(scmp(apiname, "base") or scmp(apiname, "imagebase") or scmp(apiname, "header")) //get loaded base + addr = modbase; + else if(scmp(apiname, "entry") or scmp(apiname, "oep") or scmp(apiname, "ep")) //get entry point + addr = modbase + GetPE32DataW(szModName, 0, UE_OEP); + else if(*apiname == '$') //RVA { - if(scmp(apiname, "base") or scmp(apiname, "imagebase") or scmp(apiname, "header")) //get loaded base - addr = modbase; - else if(scmp(apiname, "entry") or scmp(apiname, "oep") or scmp(apiname, "ep")) //get entry point - addr = modbase + GetPE32DataW(szModName, 0, UE_OEP); - else if(*apiname == '$') //RVA + uint rva; + if(valfromstring(apiname + 1, &rva)) + addr = modbase + rva; + } + else if(*apiname == '#') //File Offset + { + uint offset; + if(valfromstring(apiname + 1, &offset)) + addr = valfileoffsettova(modname, offset); + } + else + { + if(noexports) //get the exported functions with the '?' delimiter { - uint rva; - if(valfromstring(apiname + 1, &rva)) - addr = modbase + rva; - } - else if(*apiname == '#') //File Offset - { - uint offset; - if(valfromstring(apiname + 1, &offset)) - addr = valfileoffsettova(modname, offset); + addr = (uint)GetProcAddress(mod, apiname); + if(addr) //found exported function + addr = modbase + (addr - (uint)mod); //correct for loaded base } else { uint ordinal; if(valfromstring(apiname, &ordinal)) { - addr = noexports ? 0 : (uint)GetProcAddress(mod, (LPCSTR)(ordinal & 0xFFFF)); + addr = (uint)GetProcAddress(mod, (LPCSTR)(ordinal & 0xFFFF)); if(addr) //found exported function addr = modbase + (addr - (uint)mod); //correct for loaded base else if(!ordinal) //support for getting the image base using :0 @@ -1250,25 +1258,23 @@ bool valapifromstring(const char* name, uint* value, int* value_size, bool print } } } - FreeLibrary(mod); - if(addr) //found! - { - if(value_size) - *value_size = sizeof(uint); - if(hexonly) - *hexonly = true; - *value = addr; - return true; - } + } + FreeLibrary(mod); + if(addr) //found! + { + if(value_size) + *value_size = sizeof(uint); + if(hexonly) + *hexonly = true; + *value = addr; + return true; } } - else if(!silent) - dputs("unknown error"); } return false; } int found = 0; - int kernelbase = -1; + int kernel32 = -1; DWORD cbNeeded = 0; Memory addrfound; if(EnumProcessModules(fdProcessInfo->hProcess, 0, 0, &cbNeeded)) @@ -1282,7 +1288,7 @@ bool valapifromstring(const char* name, uint* value, int* value_size, bool print wchar_t szModuleName[MAX_PATH] = L""; if(GetModuleFileNameExW(fdProcessInfo->hProcess, hMods[i], szModuleName, MAX_PATH)) { - wchar_t* szBaseName = wcschr(szModuleName, L'\\'); + wchar_t* szBaseName = wcsrchr(szModuleName, L'\\'); if(szBaseName) { szBaseName++; @@ -1292,8 +1298,8 @@ bool valapifromstring(const char* name, uint* value, int* value_size, bool print ULONG_PTR funcAddress = (ULONG_PTR)GetProcAddress(hModule, name); if(funcAddress) { - if(!_wcsicmp(szBaseName, L"kernelbase.dll")) - kernelbase = found; + if(!_wcsicmp(szBaseName, L"kernel32.dll")) + kernel32 = found; uint rva = funcAddress - (uint)hModule; addrfound[found] = (uint)hMods[i] + rva; found++; @@ -1311,13 +1317,13 @@ bool valapifromstring(const char* name, uint* value, int* value_size, bool print *value_size = sizeof(uint); if(hexonly) *hexonly = true; - if(kernelbase != -1) + if(kernel32 != -1) //prioritize kernel32 exports { - *value = addrfound[kernelbase]; + *value = addrfound[kernel32]; if(!printall or silent) return true; for(int i = 0; i < found; i++) - if(i != kernelbase) + if(i != kernel32) dprintf(fhex"\n", addrfound[i]); } else From 0cf41d2d55cad69f6456a00fd7fb1ad2b94bf9a2 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Mon, 29 Dec 2014 02:10:39 +0100 Subject: [PATCH 11/16] GUI: better view of imports ("[module].[label]" instead of "[label]") --- x64_dbg_gui/Project/Src/Gui/CPUDump.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x64_dbg_gui/Project/Src/Gui/CPUDump.cpp b/x64_dbg_gui/Project/Src/Gui/CPUDump.cpp index 58c8322d..3ca26842 100644 --- a/x64_dbg_gui/Project/Src/Gui/CPUDump.cpp +++ b/x64_dbg_gui/Project/Src/Gui/CPUDump.cpp @@ -427,9 +427,11 @@ QString CPUDump::paintContent(QPainter* painter, int_t rowBase, int rowOffset, i uint_t data = 0; int_t wRva = (rowBase + rowOffset) * getBytePerRowCount() - mByteOffset; mMemPage->read((byte_t*)&data, wRva, sizeof(uint_t)); + char modname[MAX_MODULE_SIZE] = ""; + DbgGetModuleAt(data, modname); char label_text[MAX_LABEL_SIZE] = ""; if(DbgGetLabelAt(data, SEG_DEFAULT, label_text)) - wStr = QString(label_text); + wStr = QString(modname) + "." + QString(label_text); } else //data { From 91beff62119ef5b45cd3aa1bc8638df7355fc806 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Mon, 29 Dec 2014 15:10:34 +0100 Subject: [PATCH 12/16] GUI: added INT3 color customization --- x64_dbg_gui/Project/Src/Disassembler/BeaTokenizer.cpp | 3 +++ x64_dbg_gui/Project/Src/Disassembler/BeaTokenizer.h | 1 + x64_dbg_gui/Project/Src/Gui/AppearanceDialog.cpp | 1 + x64_dbg_gui/Project/Src/Utils/Configuration.cpp | 2 ++ 4 files changed, 7 insertions(+) diff --git a/x64_dbg_gui/Project/Src/Disassembler/BeaTokenizer.cpp b/x64_dbg_gui/Project/Src/Disassembler/BeaTokenizer.cpp index 10b05d1e..c3765237 100644 --- a/x64_dbg_gui/Project/Src/Disassembler/BeaTokenizer.cpp +++ b/x64_dbg_gui/Project/Src/Disassembler/BeaTokenizer.cpp @@ -136,6 +136,8 @@ void BeaTokenizer::Mnemonic(BeaInstructionToken* instr, const DISASM* disasm) type = TokenMnemonicPushPop; else if(IsNopInstruction(mnemonic, disasm)) //nop instructions type = TokenMnemonicNop; + else if(mnemonic == "int3" || mnemonic == "int 3") //int3 instruction on request + type = TokenMnemonicInt3; else if(completeInstr.contains("movs") || completeInstr.contains("cmps") || completeInstr.contains("scas") || completeInstr.contains("lods") || completeInstr.contains("stos") || completeInstr.contains("outs")) { completeInstr = completeInstr.replace("rep ", "").replace("repne ", ""); @@ -470,6 +472,7 @@ void BeaTokenizer::Init() AddColorName(TokenMnemonicUncondJump, "InstructionUnconditionalJumpColor", "InstructionUnconditionalJumpBackgroundColor"); AddColorName(TokenMnemonicNop, "InstructionNopColor", "InstructionNopBackgroundColor"); AddColorName(TokenMnemonicFar, "InstructionFarColor", "InstructionFarBackgroundColor"); + AddColorName(TokenMnemonicInt3, "InstructionInt3Color", "InstructionInt3BackgroundColor"); //memory AddColorName(TokenMemorySize, "InstructionMemorySizeColor", "InstructionMemorySizeBackgroundColor"); AddColorName(TokenMemorySegment, "InstructionMemorySegmentColor", "InstructionMemorySegmentBackgroundColor"); diff --git a/x64_dbg_gui/Project/Src/Disassembler/BeaTokenizer.h b/x64_dbg_gui/Project/Src/Disassembler/BeaTokenizer.h index 0bf33707..076dce6a 100644 --- a/x64_dbg_gui/Project/Src/Disassembler/BeaTokenizer.h +++ b/x64_dbg_gui/Project/Src/Disassembler/BeaTokenizer.h @@ -33,6 +33,7 @@ public: TokenMnemonicUncondJump, TokenMnemonicNop, TokenMnemonicFar, + TokenMnemonicInt3, //memory TokenMemorySize, TokenMemorySegment, diff --git a/x64_dbg_gui/Project/Src/Gui/AppearanceDialog.cpp b/x64_dbg_gui/Project/Src/Gui/AppearanceDialog.cpp index 5f5a9823..410284ed 100644 --- a/x64_dbg_gui/Project/Src/Gui/AppearanceDialog.cpp +++ b/x64_dbg_gui/Project/Src/Gui/AppearanceDialog.cpp @@ -476,6 +476,7 @@ void AppearanceDialog::colorInfoListInit() colorInfoListAppend("Unconditional Jumps", "InstructionUnconditionalJumpColor", "InstructionUnconditionalJumpBackgroundColor"); colorInfoListAppend("NOPs", "InstructionNopColor", "InstructionNopBackgroundColor"); colorInfoListAppend("FAR", "InstructionFarColor", "InstructionFarBackgroundColor"); + colorInfoListAppend("INT3s", "InstructionInt3Color", "InstructionInt3BackgroundColor"); colorInfoListAppend("General Registers", "InstructionGeneralRegisterColor", "InstructionGeneralRegisterBackgroundColor"); colorInfoListAppend("FPU Registers", "InstructionFpuRegisterColor", "InstructionFpuRegisterBackgroundColor"); colorInfoListAppend("SSE Registers", "InstructionSseRegisterColor", "InstructionSseRegisterBackgroundColor"); diff --git a/x64_dbg_gui/Project/Src/Utils/Configuration.cpp b/x64_dbg_gui/Project/Src/Utils/Configuration.cpp index cd55f46e..0bcca800 100644 --- a/x64_dbg_gui/Project/Src/Utils/Configuration.cpp +++ b/x64_dbg_gui/Project/Src/Utils/Configuration.cpp @@ -88,6 +88,8 @@ Configuration::Configuration() : QObject() defaultColors.insert("InstructionNopBackgroundColor", Qt::transparent); defaultColors.insert("InstructionFarColor", QColor("#000000")); defaultColors.insert("InstructionFarBackgroundColor", Qt::transparent); + defaultColors.insert("InstructionInt3Color", QColor("#000000")); + defaultColors.insert("InstructionInt3BackgroundColor", Qt::transparent); defaultColors.insert("InstructionMemorySizeColor", QColor("#000080")); defaultColors.insert("InstructionMemorySizeBackgroundColor", Qt::transparent); defaultColors.insert("InstructionMemorySegmentColor", QColor("#FF00FF")); From efe2f12219423e49a4eb8af4f3c94b04f4507f6e Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Mon, 29 Dec 2014 20:21:51 +0100 Subject: [PATCH 13/16] GUI: fixed a bug with copying the wrong number of instructions (thanks to futureproof for the find!) --- x64_dbg_gui/Project/Src/BasicView/Disassembly.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/x64_dbg_gui/Project/Src/BasicView/Disassembly.cpp b/x64_dbg_gui/Project/Src/BasicView/Disassembly.cpp index 16570069..c24b8dca 100644 --- a/x64_dbg_gui/Project/Src/BasicView/Disassembly.cpp +++ b/x64_dbg_gui/Project/Src/BasicView/Disassembly.cpp @@ -1175,13 +1175,11 @@ void Disassembly::prepareDataRange(int_t startRva, int_t endRva, QList Date: Tue, 30 Dec 2014 00:38:38 +0100 Subject: [PATCH 14/16] DBG: new tabbed reference view code --- x64_dbg_bridge/bridgemain.cpp | 5 +++++ x64_dbg_bridge/bridgemain.h | 9 +++++---- x64_dbg_dbg/instruction.cpp | 38 +++++++++++++++++------------------ x64_dbg_dbg/reference.cpp | 11 ++++++++-- x64_dbg_dbg/reference.h | 3 ++- 5 files changed, 40 insertions(+), 26 deletions(-) diff --git a/x64_dbg_bridge/bridgemain.cpp b/x64_dbg_bridge/bridgemain.cpp index aed60351..595a1f0f 100644 --- a/x64_dbg_bridge/bridgemain.cpp +++ b/x64_dbg_bridge/bridgemain.cpp @@ -848,6 +848,11 @@ BRIDGE_IMPEXP void GuiReferenceDeleteAllColumns() _gui_sendmessage(GUI_REF_DELETEALLCOLUMNS, 0, 0); } +BRIDGE_IMPEXP void GuiReferenceInitialize(const char* name) +{ + _gui_sendmessage(GUI_REF_INITIALIZE, (void*)name, 0); +} + BRIDGE_IMPEXP void GuiReferenceSetCellContent(int row, int col, const char* str) { CELLINFO info; diff --git a/x64_dbg_bridge/bridgemain.h b/x64_dbg_bridge/bridgemain.h index 1745d8bf..09f961f4 100644 --- a/x64_dbg_bridge/bridgemain.h +++ b/x64_dbg_bridge/bridgemain.h @@ -724,16 +724,16 @@ typedef enum GUI_GETLINE_WINDOW, // param1=const char* title, param2=char* text GUI_AUTOCOMPLETE_ADDCMD, // param1=const char* cmd, param2=ununsed GUI_AUTOCOMPLETE_DELCMD, // param1=const char* cmd, param2=ununsed - GUI_AUTOCOMPLETE_CLEARALL, // param1=ununsed, param2=unused + GUI_AUTOCOMPLETE_CLEARALL, // param1=unused, param2=unused GUI_SCRIPT_ENABLEHIGHLIGHTING, // param1=bool enable, param2=unused GUI_ADD_MSG_TO_STATUSBAR, // param1=const char* msg, param2=unused GUI_UPDATE_SIDEBAR, // param1=unused, param2=unused GUI_REPAINT_TABLE_VIEW, // param1=unused, param2=unused GUI_UPDATE_PATCHES, // param1=unused, param2=unused GUI_UPDATE_CALLSTACK, // param1=unused, param2=unused - GUI_SYMBOL_REFRESH_CURRENT, // param1=unused, param2=unused - GUI_UPDATE_MEMORY_VIEW // param1=unused, param2=unused - + GUI_SYMBOL_REFRESH_CURRENT, // param1=unused, param2=unused + GUI_UPDATE_MEMORY_VIEW, // param1=unused, param2=unused + GUI_REF_INITIALIZE // param1=const char* name param2=unused } GUIMSG; //GUI structures @@ -780,6 +780,7 @@ BRIDGE_IMPEXP void GuiReferenceAddColumn(int width, const char* title); BRIDGE_IMPEXP void GuiReferenceSetRowCount(int count); BRIDGE_IMPEXP int GuiReferenceGetRowCount(); BRIDGE_IMPEXP void GuiReferenceDeleteAllColumns(); +BRIDGE_IMPEXP void GuiReferenceInitialize(const char* name); BRIDGE_IMPEXP void GuiReferenceSetCellContent(int row, int col, const char* str); BRIDGE_IMPEXP const char* GuiReferenceGetCellContent(int row, int col); BRIDGE_IMPEXP void GuiReferenceReloadData(); diff --git a/x64_dbg_dbg/instruction.cpp b/x64_dbg_dbg/instruction.cpp index e9851a13..027ad13f 100644 --- a/x64_dbg_dbg/instruction.cpp +++ b/x64_dbg_dbg/instruction.cpp @@ -760,7 +760,7 @@ CMDRESULT cbInstrXor(int argc, char* argv[]) CMDRESULT cbInstrRefinit(int argc, char* argv[]) { - GuiReferenceDeleteAllColumns(); + GuiReferenceInitialize("Script"); GuiReferenceAddColumn(sizeof(uint) * 2, "Address"); GuiReferenceAddColumn(0, "Data"); GuiReferenceSetRowCount(0); @@ -800,9 +800,9 @@ struct VALUERANGE //reffind value[,page] static bool cbRefFind(DISASM* disasm, BASIC_INSTRUCTION_INFO* basicinfo, REFINFO* refinfo) { - if(!refinfo) //initialize + if(!disasm && !basicinfo) //initialize { - GuiReferenceDeleteAllColumns(); + GuiReferenceInitialize(refinfo->name); GuiReferenceAddColumn(2 * sizeof(uint), "Address"); GuiReferenceAddColumn(0, "Disassembly"); GuiReferenceReloadData(); @@ -880,7 +880,7 @@ CMDRESULT cbInstrRefFindRange(int argc, char* argv[]) if(!valfromstring(argv[4], &size)) size = 0; uint ticks = GetTickCount(); - int found = reffind(addr, size, cbRefFind, &range, false); + int found = reffind(addr, size, cbRefFind, &range, false, "Constant"); dprintf("%u reference(s) in %ums\n", found, GetTickCount() - ticks); varset("$result", found, false); return STATUS_CONTINUE; @@ -889,9 +889,9 @@ CMDRESULT cbInstrRefFindRange(int argc, char* argv[]) //refstr [page] bool cbRefStr(DISASM* disasm, BASIC_INSTRUCTION_INFO* basicinfo, REFINFO* refinfo) { - if(!refinfo) //initialize + if(!disasm && !basicinfo) //initialize { - GuiReferenceDeleteAllColumns(); + GuiReferenceInitialize(refinfo->name); GuiReferenceAddColumn(2 * sizeof(uint), "Address"); GuiReferenceAddColumn(64, "Disassembly"); GuiReferenceAddColumn(500, "String"); @@ -945,7 +945,7 @@ CMDRESULT cbInstrRefStr(int argc, char* argv[]) if(!valfromstring(argv[2], &size, true)) size = 0; uint ticks = GetTickCount(); - int found = reffind(addr, size, cbRefStr, 0, false); + int found = reffind(addr, size, cbRefStr, 0, false, "Strings"); dprintf("%u string(s) in %ums\n", found, GetTickCount() - ticks); varset("$result", found, false); return STATUS_CONTINUE; @@ -1160,7 +1160,7 @@ CMDRESULT cbInstrFindAll(int argc, char* argv[]) else find_size = size - start; //setup reference view - GuiReferenceDeleteAllColumns(); + GuiReferenceInitialize("Occurrences"); GuiReferenceAddColumn(2 * sizeof(uint), "Address"); if(findData) GuiReferenceAddColumn(0, "&Data&"); @@ -1209,9 +1209,9 @@ CMDRESULT cbInstrFindAll(int argc, char* argv[]) //modcallfind [page] static bool cbModCallFind(DISASM* disasm, BASIC_INSTRUCTION_INFO* basicinfo, REFINFO* refinfo) { - if(!refinfo) //initialize + if(!disasm && !basicinfo) //initialize { - GuiReferenceDeleteAllColumns(); + GuiReferenceInitialize(refinfo->name); GuiReferenceAddColumn(2 * sizeof(uint), "Address"); GuiReferenceAddColumn(0, "Disassembly"); GuiReferenceReloadData(); @@ -1249,7 +1249,7 @@ CMDRESULT cbInstrModCallFind(int argc, char* argv[]) if(!valfromstring(argv[2], &size, true)) size = 0; uint ticks = GetTickCount(); - int found = reffind(addr, size, cbModCallFind, 0, false); + int found = reffind(addr, size, cbModCallFind, 0, false, "Calls"); dprintf("%u call(s) in %ums\n", found, GetTickCount() - ticks); varset("$result", found, false); return STATUS_CONTINUE; @@ -1258,7 +1258,7 @@ CMDRESULT cbInstrModCallFind(int argc, char* argv[]) CMDRESULT cbInstrCommentList(int argc, char* argv[]) { //setup reference view - GuiReferenceDeleteAllColumns(); + GuiReferenceInitialize("Comments"); GuiReferenceAddColumn(2 * sizeof(uint), "Address"); GuiReferenceAddColumn(64, "Disassembly"); GuiReferenceAddColumn(0, "Comment"); @@ -1293,7 +1293,7 @@ CMDRESULT cbInstrCommentList(int argc, char* argv[]) CMDRESULT cbInstrLabelList(int argc, char* argv[]) { //setup reference view - GuiReferenceDeleteAllColumns(); + GuiReferenceInitialize("Labels"); GuiReferenceAddColumn(2 * sizeof(uint), "Address"); GuiReferenceAddColumn(64, "Disassembly"); GuiReferenceAddColumn(0, "Label"); @@ -1328,7 +1328,7 @@ CMDRESULT cbInstrLabelList(int argc, char* argv[]) CMDRESULT cbInstrBookmarkList(int argc, char* argv[]) { //setup reference view - GuiReferenceDeleteAllColumns(); + GuiReferenceInitialize("Bookmarks"); GuiReferenceAddColumn(2 * sizeof(uint), "Address"); GuiReferenceAddColumn(0, "Disassembly"); GuiReferenceReloadData(); @@ -1361,7 +1361,7 @@ CMDRESULT cbInstrBookmarkList(int argc, char* argv[]) CMDRESULT cbInstrFunctionList(int argc, char* argv[]) { //setup reference view - GuiReferenceDeleteAllColumns(); + GuiReferenceInitialize("Functions"); GuiReferenceAddColumn(2 * sizeof(uint), "Start"); GuiReferenceAddColumn(2 * sizeof(uint), "End"); GuiReferenceAddColumn(64, "Disassembly (Start)"); @@ -1407,7 +1407,7 @@ CMDRESULT cbInstrFunctionList(int argc, char* argv[]) CMDRESULT cbInstrLoopList(int argc, char* argv[]) { //setup reference view - GuiReferenceDeleteAllColumns(); + GuiReferenceInitialize("Loops"); GuiReferenceAddColumn(2 * sizeof(uint), "Start"); GuiReferenceAddColumn(2 * sizeof(uint), "End"); GuiReferenceAddColumn(64, "Disassembly (Start)"); @@ -1465,9 +1465,9 @@ CMDRESULT cbInstrSleep(int argc, char* argv[]) //reffindasm value[,page] static bool cbFindAsm(DISASM* disasm, BASIC_INSTRUCTION_INFO* basicinfo, REFINFO* refinfo) { - if(!refinfo) //initialize + if(!disasm && !basicinfo) //initialize { - GuiReferenceDeleteAllColumns(); + GuiReferenceInitialize(refinfo->name); GuiReferenceAddColumn(2 * sizeof(uint), "Address"); GuiReferenceAddColumn(0, "Disassembly"); GuiReferenceReloadData(); @@ -1519,7 +1519,7 @@ CMDRESULT cbInstrFindAsm(int argc, char* argv[]) disasmfast(dest, addr + size / 2, &basicinfo); uint ticks = GetTickCount(); - int found = reffind(addr, size, cbFindAsm, (void*)&basicinfo.instruction[0], false); + int found = reffind(addr, size, cbFindAsm, (void*)&basicinfo.instruction[0], false, "Command"); dprintf("%u result(s) in %ums\n", found, GetTickCount() - ticks); varset("$result", found, false); return STATUS_CONTINUE; diff --git a/x64_dbg_dbg/reference.cpp b/x64_dbg_dbg/reference.cpp index 4e6b7078..a696ede8 100644 --- a/x64_dbg_dbg/reference.cpp +++ b/x64_dbg_dbg/reference.cpp @@ -3,7 +3,7 @@ #include "memory.h" #include "console.h" -int reffind(uint addr, uint size, CBREF cbRef, void* userinfo, bool silent) +int reffind(uint addr, uint size, CBREF cbRef, void* userinfo, bool silent, const char* name) { uint start_addr; uint start_size; @@ -47,10 +47,17 @@ int reffind(uint addr, uint size, CBREF cbRef, void* userinfo, bool silent) disasm.VirtualAddr = (UInt64)start_addr; uint i = 0; BASIC_INSTRUCTION_INFO basicinfo; - cbRef(&disasm, &basicinfo, 0); //allow initializing REFINFO refinfo; memset(&refinfo, 0, sizeof(REFINFO)); refinfo.userinfo = userinfo; + char fullName[deflen] = ""; + char modname[MAX_MODULE_SIZE] = ""; + if(modnamefromaddr(start_addr, modname, true)) + sprintf_s(fullName, "%s (%s)", name, modname); + else + sprintf_s(fullName, "%s (%p)", name, start_addr); + refinfo.name = fullName; + cbRef(0, 0, &refinfo); //allow initializing while(i < start_size) { if(!(i % 0x1000)) diff --git a/x64_dbg_dbg/reference.h b/x64_dbg_dbg/reference.h index e862f473..d78a4540 100644 --- a/x64_dbg_dbg/reference.h +++ b/x64_dbg_dbg/reference.h @@ -9,12 +9,13 @@ struct REFINFO { int refcount; void* userinfo; + const char* name; }; //typedefs typedef bool (*CBREF)(DISASM* disasm, BASIC_INSTRUCTION_INFO* basicinfo, REFINFO* refinfo); //functions -int reffind(uint page, uint size, CBREF cbRef, void* userinfo, bool silent); +int reffind(uint page, uint size, CBREF cbRef, void* userinfo, bool silent, const char* name); #endif //_REFERENCE_H From 13eaa8a7aeb00bc6bd892b0fcc9b528c4a41b8fb Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Tue, 30 Dec 2014 00:54:13 +0100 Subject: [PATCH 15/16] GUI: added options for detach/delete tabs in MHTabWidget --- x64_dbg_gui/Project/Src/Gui/TabBar.cpp | 19 ++++++++++++++++--- x64_dbg_gui/Project/Src/Gui/TabBar.h | 6 +++++- x64_dbg_gui/Project/Src/Gui/TabWidget.cpp | 11 +++++++++-- x64_dbg_gui/Project/Src/Gui/TabWidget.h | 5 ++++- 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/x64_dbg_gui/Project/Src/Gui/TabBar.cpp b/x64_dbg_gui/Project/Src/Gui/TabBar.cpp index 69be9960..2fef8e37 100644 --- a/x64_dbg_gui/Project/Src/Gui/TabBar.cpp +++ b/x64_dbg_gui/Project/Src/Gui/TabBar.cpp @@ -14,8 +14,10 @@ ////////////////////////////////////////////////////////////// // Default Constructor ////////////////////////////////////////////////////////////// -MHTabBar::MHTabBar(QWidget* parent) : QTabBar(parent) +MHTabBar::MHTabBar(QWidget* parent, bool allowDetach, bool allowDelete) : QTabBar(parent) { + mAllowDetach = allowDetach; + mAllowDelete = allowDelete; setAcceptDrops(true); setElideMode(Qt::ElideRight); setSelectionBehaviorOnRemove(QTabBar::SelectLeftTab); @@ -31,14 +33,25 @@ MHTabBar::~MHTabBar(void) void MHTabBar::contextMenuEvent(QContextMenuEvent* event) { + if(!mAllowDetach && !mAllowDelete) + return; QMenu wMenu(this); QAction wDetach("&Detach", this); - wMenu.addAction(&wDetach); - if(wMenu.exec(event->globalPos()) == &wDetach) + if(mAllowDetach) + wMenu.addAction(&wDetach); + QAction wDelete("&Delete", this); + if(mAllowDelete) + wMenu.addAction(&wDelete); + QAction* executed = wMenu.exec(event->globalPos()); + if(executed == &wDetach) { QPoint p(0, 0); OnDetachTab((int)tabAt(event->pos()), p); } + else if(executed == &wDelete) + { + OnDeleteTab((int)tabAt(event->pos())); + } } diff --git a/x64_dbg_gui/Project/Src/Gui/TabBar.h b/x64_dbg_gui/Project/Src/Gui/TabBar.h index 3e456247..affb236d 100644 --- a/x64_dbg_gui/Project/Src/Gui/TabBar.h +++ b/x64_dbg_gui/Project/Src/Gui/TabBar.h @@ -18,7 +18,7 @@ class MHTabBar: public QTabBar { Q_OBJECT public: - MHTabBar(QWidget* parent); + MHTabBar(QWidget* parent, bool allowDetach, bool allowDelete); ~MHTabBar(void); protected: @@ -36,8 +36,12 @@ signals: void OnDetachTab(int index, QPoint & dropPoint); // Move Tab void OnMoveTab(int fromIndex, int toIndex); + // Delete Tab + void OnDeleteTab(int index); private: + bool mAllowDetach; + bool mAllowDelete; /* QPoint m_dragStartPos; QPoint m_dragMovedPos; diff --git a/x64_dbg_gui/Project/Src/Gui/TabWidget.cpp b/x64_dbg_gui/Project/Src/Gui/TabWidget.cpp index 46317380..f7e0ef6d 100644 --- a/x64_dbg_gui/Project/Src/Gui/TabWidget.cpp +++ b/x64_dbg_gui/Project/Src/Gui/TabWidget.cpp @@ -5,11 +5,12 @@ ////////////////////////////////////////////////////////////// // Default Constructor ////////////////////////////////////////////////////////////// -MHTabWidget::MHTabWidget(QWidget* parent) : QTabWidget(parent) +MHTabWidget::MHTabWidget(QWidget* parent, bool allowDetach, bool allowDelete) : QTabWidget(parent) { - m_tabBar = new MHTabBar(this); + m_tabBar = new MHTabBar(this, allowDetach, allowDelete); connect(m_tabBar, SIGNAL(OnDetachTab(int, QPoint &)), this, SLOT(DetachTab(int, QPoint &))); connect(m_tabBar, SIGNAL(OnMoveTab(int, int)), this, SLOT(MoveTab(int, int))); + connect(m_tabBar, SIGNAL(OnDeleteTab(int)), this, SLOT(DeleteTab(int))); setTabBar(m_tabBar); setMovable(true); @@ -29,6 +30,7 @@ MHTabWidget::~MHTabWidget(void) { disconnect(m_tabBar, SIGNAL(OnMoveTab(int, int)), this, SLOT(MoveTab(int, int))); disconnect(m_tabBar, SIGNAL(OnDetachTab(int, QPoint &)), this, SLOT(DetachTab(int, QPoint &))); + disconnect(m_tabBar, SIGNAL(OnDeleteTab(int)), this, SLOT(DeleteTab(int))); delete m_tabBar; } @@ -120,6 +122,11 @@ void MHTabWidget::DetachTab(int index, QPoint & dropPoint) detachedWidget->showNormal(); } +void MHTabWidget::DeleteTab(int index) +{ + removeTab(index); +} + ////////////////////////////////////////////////////////////////////////////// void MHTabWidget::AttachTab(QWidget* parent) { diff --git a/x64_dbg_gui/Project/Src/Gui/TabWidget.h b/x64_dbg_gui/Project/Src/Gui/TabWidget.h index 2c4411d2..762d98a6 100644 --- a/x64_dbg_gui/Project/Src/Gui/TabWidget.h +++ b/x64_dbg_gui/Project/Src/Gui/TabWidget.h @@ -22,7 +22,7 @@ class MHTabWidget: public QTabWidget Q_OBJECT public: - MHTabWidget(QWidget* parent); + MHTabWidget(QWidget* parent, bool allowDetach = true, bool allowDelete = false); virtual ~MHTabWidget(void); QTabBar* tabBar(); @@ -39,6 +39,9 @@ public slots: // Attach Tab void AttachTab(QWidget* parent); + // Delete Tab + void DeleteTab(int index); + public Q_SLOTS: void setCurrentIndex(int index); void setCurrentWidget(QWidget* widget); From 4ce848d21b04d998c08a3a29f243818416eb3e16 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Tue, 30 Dec 2014 01:11:13 +0100 Subject: [PATCH 16/16] GUI: resolved issue #125 (tabbed reference view) --- .../Project/Src/BasicView/ReferenceView.cpp | 27 +++++++---------- .../Project/Src/BasicView/ReferenceView.h | 2 +- x64_dbg_gui/Project/Src/Bridge/Bridge.cpp | 29 +++++++++++++------ x64_dbg_gui/Project/Src/Bridge/Bridge.h | 8 ++--- x64_dbg_gui/Project/Src/Gui/MainWindow.cpp | 20 ++++++------- x64_dbg_gui/Project/Src/Gui/MainWindow.h | 4 +-- .../Project/Src/Gui/ReferenceManager.cpp | 25 ++++++++++++++++ .../Project/Src/Gui/ReferenceManager.h | 24 +++++++++++++++ x64_dbg_gui/Project/x64_dbg.pro | 6 ++-- 9 files changed, 101 insertions(+), 44 deletions(-) create mode 100644 x64_dbg_gui/Project/Src/Gui/ReferenceManager.cpp create mode 100644 x64_dbg_gui/Project/Src/Gui/ReferenceManager.h diff --git a/x64_dbg_gui/Project/Src/BasicView/ReferenceView.cpp b/x64_dbg_gui/Project/Src/BasicView/ReferenceView.cpp index 25ea8409..428fec2a 100644 --- a/x64_dbg_gui/Project/Src/BasicView/ReferenceView.cpp +++ b/x64_dbg_gui/Project/Src/BasicView/ReferenceView.cpp @@ -20,7 +20,6 @@ ReferenceView::ReferenceView() // Setup signals connect(Bridge::getBridge(), SIGNAL(referenceAddColumnAt(int, QString)), this, SLOT(addColumnAt(int, QString))); connect(Bridge::getBridge(), SIGNAL(referenceSetRowCount(int_t)), this, SLOT(setRowCount(int_t))); - connect(Bridge::getBridge(), SIGNAL(referenceDeleteAllColumns()), this, SLOT(deleteAllColumns())); connect(Bridge::getBridge(), SIGNAL(referenceSetCellContent(int, int, QString)), this, SLOT(setCellContent(int, int, QString))); connect(Bridge::getBridge(), SIGNAL(referenceReloadData()), this, SLOT(reloadData())); connect(Bridge::getBridge(), SIGNAL(referenceSetSingleSelection(int, bool)), this, SLOT(setSingleSelection(int, bool))); @@ -58,6 +57,17 @@ void ReferenceView::setupContextMenu() connect(Config(), SIGNAL(shortcutsUpdated()), this, SLOT(refreshShortcutsSlot())); } +void ReferenceView::disconnectBridge() +{ + disconnect(Bridge::getBridge(), SIGNAL(referenceAddColumnAt(int, QString)), this, SLOT(addColumnAt(int, QString))); + disconnect(Bridge::getBridge(), SIGNAL(referenceSetRowCount(int_t)), this, SLOT(setRowCount(int_t))); + disconnect(Bridge::getBridge(), SIGNAL(referenceSetCellContent(int, int, QString)), this, SLOT(setCellContent(int, int, QString))); + disconnect(Bridge::getBridge(), SIGNAL(referenceReloadData()), this, SLOT(reloadData())); + disconnect(Bridge::getBridge(), SIGNAL(referenceSetSingleSelection(int, bool)), this, SLOT(setSingleSelection(int, bool))); + disconnect(Bridge::getBridge(), SIGNAL(referenceSetProgress(int)), mSearchProgress, SLOT(setValue(int))); + disconnect(Bridge::getBridge(), SIGNAL(referenceSetSearchStartCol(int)), this, SLOT(setSearchStartCol(int))); +} + void ReferenceView::refreshShortcutsSlot() { mToggleBreakpoint->setShortcut(ConfigShortcut("ActionToggleBreakpoint")); @@ -87,21 +97,6 @@ void ReferenceView::setRowCount(int_t count) mList->setRowCount(count); } -void ReferenceView::deleteAllColumns() -{ - mSearchBox->setText(""); - mList->setTableOffset(0); - mList->setSingleSelection(0); - mList->deleteAllColumns(); - mList->reloadData(); - mSearchList->setTableOffset(0); - mSearchList->setSingleSelection(0); - mSearchList->deleteAllColumns(); - mSearchList->reloadData(); - mSearchStartCol = 1; - mFollowDumpDefault = false; -} - void ReferenceView::setCellContent(int r, int c, QString s) { mSearchBox->setText(""); diff --git a/x64_dbg_gui/Project/Src/BasicView/ReferenceView.h b/x64_dbg_gui/Project/Src/BasicView/ReferenceView.h index cf032522..d94b0d4e 100644 --- a/x64_dbg_gui/Project/Src/BasicView/ReferenceView.h +++ b/x64_dbg_gui/Project/Src/BasicView/ReferenceView.h @@ -11,11 +11,11 @@ class ReferenceView : public SearchListView public: ReferenceView(); void setupContextMenu(); + void disconnectBridge(); private slots: void addColumnAt(int width, QString title); void setRowCount(int_t count); - void deleteAllColumns(); void setCellContent(int r, int c, QString s); void reloadData(); void setSingleSelection(int index, bool scroll); diff --git a/x64_dbg_gui/Project/Src/Bridge/Bridge.cpp b/x64_dbg_gui/Project/Src/Bridge/Bridge.cpp index 96adf0ff..0a30219c 100644 --- a/x64_dbg_gui/Project/Src/Bridge/Bridge.cpp +++ b/x64_dbg_gui/Project/Src/Bridge/Bridge.cpp @@ -17,7 +17,7 @@ Bridge::Bridge(QObject* parent) : QObject(parent) mBridgeMutex = new QMutex(); winId = 0; scriptView = 0; - referenceView = 0; + referenceManager = 0; bridgeResult = 0; hasBridgeResult = false; } @@ -173,11 +173,6 @@ void Bridge::emitReferenceSetRowCount(int_t count) emit referenceSetRowCount(count); } -void Bridge::emitReferenceDeleteAllColumns() -{ - emit referenceDeleteAllColumns(); -} - void Bridge::emitReferenceSetCellContent(int r, int c, QString s) { emit referenceSetCellContent(r, c, s); @@ -203,6 +198,16 @@ void Bridge::emitReferenceSetSearchStartCol(int col) emit referenceSetSearchStartCol(col); } +void Bridge::emitReferenceInitialize(QString name) +{ + mBridgeMutex->lock(); + hasBridgeResult = false; + emit referenceInitialize(name); + while(!hasBridgeResult) //wait for thread completion + Sleep(100); + mBridgeMutex->unlock(); +} + void Bridge::emitStackDumpAt(uint_t va, uint_t csp) { emit stackDumpAt(va, csp); @@ -558,13 +563,13 @@ __declspec(dllexport) void* _gui_sendmessage(GUIMSG type, void* param1, void* pa case GUI_REF_GETROWCOUNT: { - return (void*)Bridge::getBridge()->referenceView->mList->getRowCount(); + return (void*)(void*)Bridge::getBridge()->referenceManager->currentReferenceView()->mList->getRowCount(); } break; case GUI_REF_DELETEALLCOLUMNS: { - Bridge::getBridge()->emitReferenceDeleteAllColumns(); + GuiReferenceInitialize("References"); } break; @@ -577,7 +582,7 @@ __declspec(dllexport) void* _gui_sendmessage(GUIMSG type, void* param1, void* pa case GUI_REF_GETCELLCONTENT: { - return (void*)Bridge::getBridge()->referenceView->mList->getCellContent((int)(int_t)param1, (int)(int_t)param2).toUtf8().constData(); + return (void*)Bridge::getBridge()->referenceManager->currentReferenceView()->mList->getCellContent((int)(int_t)param1, (int)(int_t)param2).toUtf8().constData(); } break; @@ -605,6 +610,12 @@ __declspec(dllexport) void* _gui_sendmessage(GUIMSG type, void* param1, void* pa } break; + case GUI_REF_INITIALIZE: + { + Bridge::getBridge()->emitReferenceInitialize(QString(reinterpret_cast(param1))); + } + break; + case GUI_STACK_DUMP_AT: { Bridge::getBridge()->emitStackDumpAt((uint_t)param1, (uint_t)param2); diff --git a/x64_dbg_gui/Project/Src/Bridge/Bridge.h b/x64_dbg_gui/Project/Src/Bridge/Bridge.h index 34bb7bba..33b56e2f 100644 --- a/x64_dbg_gui/Project/Src/Bridge/Bridge.h +++ b/x64_dbg_gui/Project/Src/Bridge/Bridge.h @@ -5,7 +5,7 @@ #include #include "Imports.h" #include "NewTypes.h" -#include "SearchListView.h" +#include "ReferenceManager.h" class Bridge : public QObject { @@ -48,12 +48,12 @@ public: void emitSetSymbolProgress(int progress); void emitReferenceAddColumnAt(int width, QString title); void emitReferenceSetRowCount(int_t count); - void emitReferenceDeleteAllColumns(); void emitReferenceSetCellContent(int r, int c, QString s); void emitReferenceReloadData(); void emitReferenceSetSingleSelection(int index, bool scroll); void emitReferenceSetProgress(int progress); void emitReferenceSetSearchStartCol(int col); + void emitReferenceInitialize(QString name); void emitStackDumpAt(uint_t va, uint_t csp); void emitUpdateDump(); void emitUpdateThreads(); @@ -80,7 +80,7 @@ public: //Public variables void* winId; QWidget* scriptView; - SearchListView* referenceView; + ReferenceManager* referenceManager; signals: void disassembleAt(int_t va, int_t eip); @@ -107,12 +107,12 @@ signals: void setSymbolProgress(int progress); void referenceAddColumnAt(int width, QString title); void referenceSetRowCount(int_t count); - void referenceDeleteAllColumns(); void referenceSetCellContent(int r, int c, QString s); void referenceReloadData(); void referenceSetSingleSelection(int index, bool scroll); void referenceSetProgress(int progress); void referenceSetSearchStartCol(int col); + void referenceInitialize(QString name); void stackDumpAt(uint_t va, uint_t csp); void updateDump(); void updateThreads(); diff --git a/x64_dbg_gui/Project/Src/Gui/MainWindow.cpp b/x64_dbg_gui/Project/Src/Gui/MainWindow.cpp index 259e37e5..00d9b4a5 100644 --- a/x64_dbg_gui/Project/Src/Gui/MainWindow.cpp +++ b/x64_dbg_gui/Project/Src/Gui/MainWindow.cpp @@ -82,11 +82,11 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi mCpuWidget->setWindowTitle("CPU"); mCpuWidget->setWindowIcon(QIcon(":/icons/images/processor-cpu.png")); - // Reference View - mReferenceView = new ReferenceView(); - Bridge::getBridge()->referenceView = mReferenceView; - mReferenceView->setWindowTitle("References"); - mReferenceView->setWindowIcon(QIcon(":/icons/images/search.png")); + // Reference Manager + mReferenceManager = new ReferenceManager(); + Bridge::getBridge()->referenceManager = mReferenceManager; + mReferenceManager->setWindowTitle("References"); + mReferenceManager->setWindowIcon(QIcon(":/icons/images/search.png")); // Thread View mThreadView = new ThreadView(); @@ -105,7 +105,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi mTabWidget->addTab(mCallStackView, mCallStackView->windowIcon(), mCallStackView->windowTitle()); mTabWidget->addTab(mScriptView, mScriptView->windowIcon(), mScriptView->windowTitle()); mTabWidget->addTab(mSymbolView, mSymbolView->windowIcon(), mSymbolView->windowTitle()); - mTabWidget->addTab(mReferenceView, mReferenceView->windowIcon(), mReferenceView->windowTitle()); + mTabWidget->addTab(mReferenceManager, mReferenceManager->windowIcon(), mReferenceManager->windowTitle()); mTabWidget->addTab(mThreadView, mThreadView->windowIcon(), mThreadView->windowTitle()); setCentralWidget(mTabWidget); @@ -152,7 +152,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi connect(ui->actionCpu, SIGNAL(triggered()), this, SLOT(displayCpuWidget())); connect(ui->actionSymbolInfo, SIGNAL(triggered()), this, SLOT(displaySymbolWidget())); connect(mSymbolView, SIGNAL(showCpu()), this, SLOT(displayCpuWidget())); - connect(mReferenceView, SIGNAL(showCpu()), this, SLOT(displayCpuWidget())); + connect(mReferenceManager, SIGNAL(showCpu()), this, SLOT(displayCpuWidget())); connect(ui->actionReferences, SIGNAL(triggered()), this, SLOT(displayReferencesWidget())); connect(ui->actionThreads, SIGNAL(triggered()), this, SLOT(displayThreadsWidget())); connect(ui->actionSettings, SIGNAL(triggered()), this, SLOT(openSettings())); @@ -644,9 +644,9 @@ void MainWindow::displaySymbolWidget() void MainWindow::displayReferencesWidget() { - mReferenceView->show(); - mReferenceView->setFocus(); - setTab(mReferenceView); + mReferenceManager->show(); + mReferenceManager->setFocus(); + setTab(mReferenceManager); } void MainWindow::displayThreadsWidget() diff --git a/x64_dbg_gui/Project/Src/Gui/MainWindow.h b/x64_dbg_gui/Project/Src/Gui/MainWindow.h index 5862b7ef..75e33498 100644 --- a/x64_dbg_gui/Project/Src/Gui/MainWindow.h +++ b/x64_dbg_gui/Project/Src/Gui/MainWindow.h @@ -13,7 +13,7 @@ #include "SymbolView.h" #include "BreakpointsView.h" #include "ScriptView.h" -#include "ReferenceView.h" +#include "ReferenceManager.h" #include "ThreadView.h" #include "PatchDialog.h" #include "CalculatorDialog.h" @@ -104,7 +104,7 @@ private: SymbolView* mSymbolView; BreakpointsView* mBreakpointsView; ScriptView* mScriptView; - ReferenceView* mReferenceView; + ReferenceManager* mReferenceManager; ThreadView* mThreadView; PatchDialog* mPatchDialog; CalculatorDialog* mCalculatorDialog; diff --git a/x64_dbg_gui/Project/Src/Gui/ReferenceManager.cpp b/x64_dbg_gui/Project/Src/Gui/ReferenceManager.cpp new file mode 100644 index 00000000..20b0499a --- /dev/null +++ b/x64_dbg_gui/Project/Src/Gui/ReferenceManager.cpp @@ -0,0 +1,25 @@ +#include "ReferenceManager.h" +#include "Bridge.h" + +ReferenceManager::ReferenceManager(QWidget* parent) : MHTabWidget(parent, false, true) +{ + this->setMovable(true); + mCurrentReferenceView = 0; + connect(Bridge::getBridge(), SIGNAL(referenceInitialize(QString)), this, SLOT(newReferenceView(QString))); +} + +ReferenceView* ReferenceManager::currentReferenceView() +{ + return mCurrentReferenceView; +} + +void ReferenceManager::newReferenceView(QString name) +{ + if(mCurrentReferenceView) //disconnect previous reference view + mCurrentReferenceView->disconnectBridge(); + mCurrentReferenceView = new ReferenceView(); + connect(mCurrentReferenceView, SIGNAL(showCpu()), this, SIGNAL(showCpu())); + insertTab(0, mCurrentReferenceView, name); + setCurrentIndex(0); + Bridge::getBridge()->BridgeSetResult(1); +} diff --git a/x64_dbg_gui/Project/Src/Gui/ReferenceManager.h b/x64_dbg_gui/Project/Src/Gui/ReferenceManager.h new file mode 100644 index 00000000..8f131ed9 --- /dev/null +++ b/x64_dbg_gui/Project/Src/Gui/ReferenceManager.h @@ -0,0 +1,24 @@ +#ifndef REFERENCEMANAGER_H +#define REFERENCEMANAGER_H + +#include "TabWidget.h" +#include "ReferenceView.h" + +class ReferenceManager : public MHTabWidget +{ + Q_OBJECT +public: + explicit ReferenceManager(QWidget* parent = 0); + ReferenceView* currentReferenceView(); + +public slots: + void newReferenceView(QString name); + +signals: + void showCpu(); + +private: + ReferenceView* mCurrentReferenceView; +}; + +#endif // REFERENCEMANAGER_H diff --git a/x64_dbg_gui/Project/x64_dbg.pro b/x64_dbg_gui/Project/x64_dbg.pro index 44dc257a..d4a70978 100644 --- a/x64_dbg_gui/Project/x64_dbg.pro +++ b/x64_dbg_gui/Project/x64_dbg.pro @@ -84,7 +84,8 @@ SOURCES += \ Src/Gui/CalculatorDialog.cpp \ Src/Gui/AttachDialog.cpp \ Src/Gui/PageMemoryRights.cpp \ - Src/Gui/SelectFields.cpp + Src/Gui/SelectFields.cpp \ + Src/Gui/ReferenceManager.cpp HEADERS += \ @@ -147,7 +148,8 @@ HEADERS += \ Src/Gui/CalculatorDialog.h \ Src/Gui/AttachDialog.h \ Src/Gui/PageMemoryRights.h \ - Src/Gui/SelectFields.h + Src/Gui/SelectFields.h \ + Src/Gui/ReferenceManager.h INCLUDEPATH += \