diff --git a/src/gui/Src/BasicView/Disassembly.cpp b/src/gui/Src/BasicView/Disassembly.cpp index 9ed125cd..a9bd587d 100644 --- a/src/gui/Src/BasicView/Disassembly.cpp +++ b/src/gui/Src/BasicView/Disassembly.cpp @@ -7,7 +7,9 @@ #include "QBeaEngine.h" #include "MemoryPage.h" -Disassembly::Disassembly(QWidget* parent) : AbstractTableView(parent) +Disassembly::Disassembly(QWidget* parent, bool isMain) + : AbstractTableView(parent), + mIsMain(isMain) { mMemPage = new MemoryPage(0, 0); @@ -905,8 +907,7 @@ void Disassembly::keyPressEvent(QKeyEvent* event) duint dest = DbgGetBranchDestination(rvaToVa(getInitialSelection())); if(!DbgMemIsValidReadPtr(dest)) return; - QString cmd = "disasm " + ToPtrString(dest); - DbgCmdExec(cmd.toUtf8().constData()); + gotoAddress(dest); } else AbstractTableView::keyPressEvent(event); @@ -1753,6 +1754,18 @@ duint Disassembly::rvaToVa(dsint rva) const return mMemPage->va(rva); } +void Disassembly::gotoAddress(duint addr) +{ + disassembleAt(addr, true, -1); + + if(mIsMain) + { + // Update window title + DbgCmdExecDirect(QString("guiupdatetitle %1").arg(ToPtrString(addr))); + } + GuiUpdateAllViews(); +} + void Disassembly::disassembleAt(dsint parVA, bool history, dsint newTableOffset) { duint wSize; @@ -1884,8 +1897,9 @@ void Disassembly::disassembleAtSlot(dsint parVA, dsint parCIP) mCodeFoldingManager->expandFoldSegment(parVA); mCodeFoldingManager->expandFoldSegment(parCIP); } - mCipVa = parCIP; // TODO: emit a signal for this? - disassembleAt(parVA, true, -1); + mCipVa = parCIP; + if(mIsMain || !mMemPage->getBase()) + disassembleAt(parVA, true, -1); } void Disassembly::disassembleClear() @@ -1943,9 +1957,12 @@ void Disassembly::historyPrevious() mCodeFoldingManager->expandFoldSegment(va); disassembleAt(va, false, mVaHistory.at(mCurrentVa).tableOffset); - // Update window title - DbgCmdExecDirect(QString("guiupdatetitle %1").arg(ToPtrString(va))); - GuiUpdateAllViews(); + if(mIsMain) + { + // Update window title + DbgCmdExecDirect(QString("guiupdatetitle %1").arg(ToPtrString(va))); + GuiUpdateAllViews(); + } } void Disassembly::historyNext() @@ -1958,9 +1975,12 @@ void Disassembly::historyNext() mCodeFoldingManager->expandFoldSegment(va); disassembleAt(va, false, mVaHistory.at(mCurrentVa).tableOffset); - // Update window title - DbgCmdExecDirect(QString("guiupdatetitle %1").arg(ToPtrString(va))); - GuiUpdateAllViews(); + if(mIsMain) + { + // Update window title + DbgCmdExecDirect(QString("guiupdatetitle %1").arg(ToPtrString(va))); + GuiUpdateAllViews(); + } } bool Disassembly::historyHasPrevious() const diff --git a/src/gui/Src/BasicView/Disassembly.h b/src/gui/Src/BasicView/Disassembly.h index 3fcdd280..f51de17f 100644 --- a/src/gui/Src/BasicView/Disassembly.h +++ b/src/gui/Src/BasicView/Disassembly.h @@ -11,7 +11,7 @@ class Disassembly : public AbstractTableView { Q_OBJECT public: - explicit Disassembly(QWidget* parent = 0); + Disassembly(QWidget* parent, bool isMain); ~Disassembly() override; // Configuration @@ -88,6 +88,7 @@ public: bool historyHasNext() const; //disassemble + void gotoAddress(duint addr); void disassembleAt(dsint parVA, bool history, dsint newTableOffset); QList* instructionsBuffer(); // ugly @@ -247,6 +248,7 @@ protected: ZydisTokenizer::SingleToken mHighlightToken; bool mPermanentHighlightingMode; bool mNoCurrentModuleText; + bool mIsMain = false; }; #endif // DISASSEMBLY_H diff --git a/src/gui/Src/Gui/CPUDisassembly.cpp b/src/gui/Src/Gui/CPUDisassembly.cpp index ae3c0389..cddf975b 100644 --- a/src/gui/Src/Gui/CPUDisassembly.cpp +++ b/src/gui/Src/Gui/CPUDisassembly.cpp @@ -26,23 +26,22 @@ #include "BreakpointMenu.h" #include "BrowseDialog.h" -CPUDisassembly::CPUDisassembly(QWidget* parent) : Disassembly(parent) +CPUDisassembly::CPUDisassembly(QWidget* parent, bool isMain) : Disassembly(parent, isMain) { setWindowTitle("Disassembly"); // Create the action list for the right click context menu setupRightClickContextMenu(); - // TODO: refactor these signals out of the class (move to CPUWidget + CPUMultiDump) - // TODO: refactor all DbgCmdExec("disasm ...") commands (customization point) - // TODO: refactor mPluginMenu to be a singleton (so plugin menus show up in all instances) - // Connect bridge<->disasm calls connect(Bridge::getBridge(), SIGNAL(disassembleAt(dsint, dsint)), this, SLOT(disassembleAtSlot(dsint, dsint))); - connect(Bridge::getBridge(), SIGNAL(selectionDisasmGet(SELECTIONDATA*)), this, SLOT(selectionGetSlot(SELECTIONDATA*))); - connect(Bridge::getBridge(), SIGNAL(selectionDisasmSet(const SELECTIONDATA*)), this, SLOT(selectionSetSlot(const SELECTIONDATA*))); - connect(Bridge::getBridge(), SIGNAL(displayWarning(QString, QString)), this, SLOT(displayWarningSlot(QString, QString))); - connect(Bridge::getBridge(), SIGNAL(focusDisasm()), this, SLOT(setFocus())); + if(mIsMain) + { + connect(Bridge::getBridge(), SIGNAL(selectionDisasmGet(SELECTIONDATA*)), this, SLOT(selectionGetSlot(SELECTIONDATA*))); + connect(Bridge::getBridge(), SIGNAL(selectionDisasmSet(const SELECTIONDATA*)), this, SLOT(selectionSetSlot(const SELECTIONDATA*))); + connect(Bridge::getBridge(), SIGNAL(displayWarning(QString, QString)), this, SLOT(displayWarningSlot(QString, QString))); + connect(Bridge::getBridge(), SIGNAL(focusDisasm()), this, SLOT(setFocus())); + } // Connect some internal signals connect(this, SIGNAL(selectionExpanded()), this, SLOT(selectionUpdatedSlot())); @@ -644,14 +643,20 @@ void CPUDisassembly::setupRightClickContextMenu() }); // Plugins - mPluginMenu = new QMenu(this); - Bridge::getBridge()->emitMenuAddToList(this, mPluginMenu, GUI_DISASM_MENU); + if(mIsMain) + { + mPluginMenu = new QMenu(this); + Bridge::getBridge()->emitMenuAddToList(this, mPluginMenu, GUI_DISASM_MENU); + } mMenuBuilder->addSeparator(); mMenuBuilder->addBuilder(new MenuBuilder(this, [this](QMenu * menu) { DbgMenuPrepare(GUI_DISASM_MENU); - menu->addActions(mPluginMenu->actions()); + if(mIsMain) + { + menu->addActions(mPluginMenu->actions()); + } return true; })); @@ -674,7 +679,7 @@ void CPUDisassembly::gotoOriginSlot() { if(!DbgIsDebugging()) return; - DbgCmdExec("disasm cip"); + gotoAddress(DbgValFromString("cip")); } void CPUDisassembly::setNewOriginHereActionSlot() @@ -1006,7 +1011,7 @@ void CPUDisassembly::gotoExpressionSlot() if(mGoto->exec() == QDialog::Accepted) { duint value = DbgValFromString(mGoto->expressionText.toUtf8().constData()); - DbgCmdExec(QString().sprintf("disasm %p", value).toUtf8().constData()); + gotoAddress(value); } } @@ -1040,19 +1045,19 @@ void CPUDisassembly::gotoFileOffsetSlot() return; duint value = DbgValFromString(mGotoOffset->expressionText.toUtf8().constData()); value = DbgFunctions()->FileOffsetToVa(modname, value); - DbgCmdExec(QString().sprintf("disasm \"%p\"", value).toUtf8().constData()); + gotoAddress(value); } void CPUDisassembly::gotoStartSlot() { duint dest = mMemPage->getBase(); - DbgCmdExec(QString().sprintf("disasm \"%p\"", dest).toUtf8().constData()); + gotoAddress(dest); } void CPUDisassembly::gotoEndSlot() { duint dest = mMemPage->getBase() + mMemPage->getSize() - (getViewableRowsCount() * 16); - DbgCmdExec(QString().sprintf("disasm \"%p\"", dest).toUtf8().constData()); + gotoAddress(dest); } void CPUDisassembly::gotoFunctionStartSlot() @@ -1060,7 +1065,7 @@ void CPUDisassembly::gotoFunctionStartSlot() duint start; if(!DbgFunctionGet(rvaToVa(getInitialSelection()), &start, nullptr)) return; - DbgCmdExec(QString("disasm \"%1\"").arg(ToHexString(start)).toUtf8().constData()); + gotoAddress(start); } void CPUDisassembly::gotoFunctionEndSlot() @@ -1068,7 +1073,7 @@ void CPUDisassembly::gotoFunctionEndSlot() duint end; if(!DbgFunctionGet(rvaToVa(getInitialSelection()), nullptr, &end)) return; - DbgCmdExec(QString("disasm \"%1\"").arg(ToHexString(end)).toUtf8().constData()); + gotoAddress(end); } void CPUDisassembly::gotoPreviousReferenceSlot() @@ -1078,7 +1083,7 @@ void CPUDisassembly::gotoPreviousReferenceSlot() { if(index > 0 && addr == rvaToVa(getInitialSelection())) DbgValToString("$__disasm_refindex", index - 1); - DbgCmdExec("disasm refsearch.addr($__disasm_refindex)"); + gotoAddress(DbgValFromString("refsearch.addr($__disasm_refindex)")); } } @@ -1089,7 +1094,7 @@ void CPUDisassembly::gotoNextReferenceSlot() { if(index + 1 < count && addr == rvaToVa(getInitialSelection())) DbgValToString("$__disasm_refindex", index + 1); - DbgCmdExec("disasm refsearch.addr($__disasm_refindex)"); + gotoAddress(DbgValFromString("refsearch.addr($__disasm_refindex)")); } } @@ -1099,7 +1104,10 @@ void CPUDisassembly::gotoXrefSlot() return; if(!mXrefDlg) mXrefDlg = new XrefBrowseDialog(this); - mXrefDlg->setup(getSelectedVa()); + mXrefDlg->setup(getSelectedVa(), [this](duint addr) + { + gotoAddress(addr); + }); mXrefDlg->showNormal(); } @@ -1120,7 +1128,7 @@ void CPUDisassembly::followActionSlot() else if(action->objectName().startsWith("CPU|")) { QString value = action->objectName().mid(4); - DbgCmdExec(QString("disasm " + value).toUtf8().constData()); + gotoAddress(DbgValFromString(value.toUtf8().constData())); } } diff --git a/src/gui/Src/Gui/CPUDisassembly.h b/src/gui/Src/Gui/CPUDisassembly.h index 63e26999..fc54a260 100644 --- a/src/gui/Src/Gui/CPUDisassembly.h +++ b/src/gui/Src/Gui/CPUDisassembly.h @@ -14,7 +14,7 @@ class CPUDisassembly : public Disassembly Q_OBJECT public: - explicit CPUDisassembly(QWidget* parent); + CPUDisassembly(QWidget* parent, bool isMain); // Mouse management void contextMenuEvent(QContextMenuEvent* event); @@ -126,7 +126,7 @@ private: // Menus QMenu* mHwSlotSelectMenu; - QMenu* mPluginMenu; + QMenu* mPluginMenu = nullptr; // Actions QAction* mReferenceSelectedAddressAction; diff --git a/src/gui/Src/Gui/CPUDump.cpp b/src/gui/Src/Gui/CPUDump.cpp index 4a52c355..50ae06c5 100644 --- a/src/gui/Src/Gui/CPUDump.cpp +++ b/src/gui/Src/Gui/CPUDump.cpp @@ -271,7 +271,7 @@ void CPUDump::setupContextMenu() mMenuBuilder->addMenu(makeMenu(DIcon("float.png"), tr("&Float")), wFloatMenu); mMenuBuilder->addAction(makeAction(DIcon("address.png"), tr("&Address"), SLOT(addressSlot()))); - mMenuBuilder->addAction(makeAction(DIcon("processor-cpu.png"), tr("&Disassembly"), SLOT(disassemblySlot())))->setEnabled(false); + mMenuBuilder->addAction(makeAction(DIcon("processor-cpu.png"), tr("&Disassembly"), SLOT(disassemblySlot()))); mMenuBuilder->addSeparator(); mMenuBuilder->addBuilder(new MenuBuilder(this, [this](QMenu * menu) @@ -1360,7 +1360,9 @@ void CPUDump::addressUnicodeSlot() void CPUDump::disassemblySlot() { - SimpleErrorBox(this, tr("Error!"), tr("Not yet supported!")); + SELECTIONDATA selection; + selectionGet(&selection); + emit showDisassemblyTab(selection.start, selection.end, rvaToVa(getTableOffsetRva())); } void CPUDump::selectionGet(SELECTIONDATA* selection) diff --git a/src/gui/Src/Gui/CPUDump.h b/src/gui/Src/Gui/CPUDump.h index aba691db..c63c4931 100644 --- a/src/gui/Src/Gui/CPUDump.h +++ b/src/gui/Src/Gui/CPUDump.h @@ -23,6 +23,7 @@ public: signals: void displayReferencesWidget(); + void showDisassemblyTab(duint selectionStart, duint selectionEnd, duint firstAddress); public slots: void memoryAccessSingleshootSlot(); diff --git a/src/gui/Src/Gui/CPUInfoBox.cpp b/src/gui/Src/Gui/CPUInfoBox.cpp index 1f78661c..6c484f17 100644 --- a/src/gui/Src/Gui/CPUInfoBox.cpp +++ b/src/gui/Src/Gui/CPUInfoBox.cpp @@ -573,7 +573,10 @@ void CPUInfoBox::findXReferencesSlot() return; if(!mXrefDlg) mXrefDlg = new XrefBrowseDialog(this); - mXrefDlg->setup(curAddr); + mXrefDlg->setup(curAddr, [](duint address) + { + DbgCmdExec(QString("disasm %1").arg(ToPtrString(address)).toUtf8().constData()); + }); mXrefDlg->showNormal(); } diff --git a/src/gui/Src/Gui/CPUMultiDump.cpp b/src/gui/Src/Gui/CPUMultiDump.cpp index 3c2e62d6..6966e19a 100644 --- a/src/gui/Src/Gui/CPUMultiDump.cpp +++ b/src/gui/Src/Gui/CPUMultiDump.cpp @@ -1,5 +1,6 @@ #include "CPUMultiDump.h" #include "CPUDump.h" +#include "CPUDisassembly.h" #include "WatchView.h" #include "LocalVarsView.h" #include "StructWidget.h" @@ -24,6 +25,7 @@ CPUMultiDump::CPUMultiDump(CPUDisassembly* disas, int nbCpuDumpTabs, QWidget* pa CPUDump* cpuDump = new CPUDump(disas, this); //cpuDump->loadColumnFromConfig(QString("CPUDump%1").arg(i + 1)); //TODO: needs a workaround because the columns change connect(cpuDump, SIGNAL(displayReferencesWidget()), this, SLOT(displayReferencesWidgetSlot())); + connect(cpuDump, SIGNAL(showDisassemblyTab(duint, duint, duint)), this, SLOT(showDisassemblyTabSlot(duint, duint, duint))); auto nativeTitle = QString("Dump ") + QString::number(i + 1); this->addTabEx(cpuDump, DIcon("dump.png"), tr("Dump ") + QString::number(i + 1), nativeTitle); cpuDump->setWindowTitle(nativeTitle); @@ -223,6 +225,28 @@ void CPUMultiDump::focusCurrentDumpSlot() mCurrentCPUDump->setFocus(); } +void CPUMultiDump::showDisassemblyTabSlot(duint selectionStart, duint selectionEnd, duint firstAddress) +{ + Q_UNUSED(firstAddress); // TODO: implement setTableOffset(firstAddress) + if(!mDisassembly) + { + mDisassembly = new CPUDisassembly(this, false); + this->addTabEx(mDisassembly, DIcon(ArchValue("processor32.png", "processor64.png")), tr("Disassembly"), "DumpDisassembly"); + } + // Set CIP + auto clearHistory = mDisassembly->getBase() == 0; + mDisassembly->disassembleAtSlot(selectionStart, Bridge::getBridge()->mLastCip); + if(clearHistory) + mDisassembly->historyClear(); + // Make the address visisble in memory + mDisassembly->disassembleAt(selectionStart, true, -1); + // Set selection to match the dump + mDisassembly->setSingleSelection(selectionStart - mDisassembly->getBase()); + mDisassembly->expandSelectionUpTo(selectionEnd - mDisassembly->getBase()); + // Show the tab + setCurrentWidget(mDisassembly); +} + void CPUMultiDump::getDumpAttention() { mCurrentCPUDump->getAttention(); diff --git a/src/gui/Src/Gui/CPUMultiDump.h b/src/gui/Src/Gui/CPUMultiDump.h index 7461ebfa..92c80acb 100644 --- a/src/gui/Src/Gui/CPUMultiDump.h +++ b/src/gui/Src/Gui/CPUMultiDump.h @@ -34,6 +34,7 @@ public slots: void openChangeTabTitleDialogSlot(int tabIndex); void displayReferencesWidgetSlot(); void focusCurrentDumpSlot(); + void showDisassemblyTabSlot(duint selectionStart, duint selectionEnd, duint firstAddress); void getDumpAttention(); private: @@ -44,6 +45,7 @@ private: WatchView* mWatch; LocalVarsView* mLocalVars; StructWidget* mStructWidget; + CPUDisassembly* mDisassembly = nullptr; int GetDumpWindowIndex(int dump); int GetWatchWindowIndex(); diff --git a/src/gui/Src/Gui/CPUWidget.cpp b/src/gui/Src/Gui/CPUWidget.cpp index dfa6559b..66c252c0 100644 --- a/src/gui/Src/Gui/CPUWidget.cpp +++ b/src/gui/Src/Gui/CPUWidget.cpp @@ -18,7 +18,7 @@ CPUWidget::CPUWidget(QWidget* parent) : QWidget(parent), ui(new Ui::CPUWidget) setStyleSheet("AbstractTableView:focus, RegistersView:focus, CPUSideBar:focus { border: 1px solid #000000; }"); - mDisas = new CPUDisassembly(this); + mDisas = new CPUDisassembly(this, true); mSideBar = new CPUSideBar(mDisas); mDisas->setSideBar(mSideBar); mArgumentWidget = new CPUArgumentWidget(this); diff --git a/src/gui/Src/Gui/DisassemblerGraphView.cpp b/src/gui/Src/Gui/DisassemblerGraphView.cpp index 9812f021..2f5a687b 100644 --- a/src/gui/Src/Gui/DisassemblerGraphView.cpp +++ b/src/gui/Src/Gui/DisassemblerGraphView.cpp @@ -2587,7 +2587,10 @@ void DisassemblerGraphView::xrefSlot() BridgeFree(mXrefInfo.references); if(!mXrefDlg) mXrefDlg = new XrefBrowseDialog(this); - mXrefDlg->setup(wVA, "graph"); + mXrefDlg->setup(wVA, [](duint addr) + { + DbgCmdExec(QString("graph %1").arg(ToPtrString(addr)).toUtf8().constData()); + }); mXrefDlg->showNormal(); } diff --git a/src/gui/Src/Gui/MainWindow.cpp b/src/gui/Src/Gui/MainWindow.cpp index 98da980a..7fd982e7 100644 --- a/src/gui/Src/Gui/MainWindow.cpp +++ b/src/gui/Src/Gui/MainWindow.cpp @@ -1679,6 +1679,8 @@ void MainWindow::executeOnGuiThread(void* cbGuiThread, void* userdata) void MainWindow::tabMovedSlot(int from, int to) { + Q_UNUSED(from); + Q_UNUSED(to); for(int i = 0; i < mTabWidget->count(); i++) { // Remove space in widget name and append Tab to get config settings (CPUTab, MemoryMapTab, etc...) diff --git a/src/gui/Src/Gui/XrefBrowseDialog.cpp b/src/gui/Src/Gui/XrefBrowseDialog.cpp index d184a6b7..f5a4f4b3 100644 --- a/src/gui/Src/Gui/XrefBrowseDialog.cpp +++ b/src/gui/Src/Gui/XrefBrowseDialog.cpp @@ -39,15 +39,15 @@ QString XrefBrowseDialog::GetFunctionSymbol(duint addr) return line; } -void XrefBrowseDialog::setup(duint address, QString command) +void XrefBrowseDialog::setup(duint address, GotoFunction gotoFunction) { if(mXrefInfo.refcount) { BridgeFree(mXrefInfo.references); mXrefInfo.refcount = 0; } - mCommand = command; mAddress = address; + mGotoFunction = std::move(gotoFunction); mPrevSelectionSize = 0; ui->listWidget->clear(); if(DbgXrefGet(address, &mXrefInfo)) @@ -161,7 +161,7 @@ void XrefBrowseDialog::setupContextMenu() void XrefBrowseDialog::changeAddress(duint address) { - DbgCmdExec(QString("%1 %2").arg(mCommand, ToPtrString(address)).toUtf8().constData()); + mGotoFunction(address); } XrefBrowseDialog::~XrefBrowseDialog() @@ -203,7 +203,7 @@ void XrefBrowseDialog::on_listWidget_currentRowChanged(int row) void XrefBrowseDialog::on_XrefBrowseDialog_rejected() { if(DbgIsDebugging()) - DbgCmdExec(QString("%1 %2").arg(mCommand, ToPtrString(mAddress)).toUtf8().constData()); + mGotoFunction(mAddress); } void XrefBrowseDialog::on_listWidget_itemClicked(QListWidgetItem*) diff --git a/src/gui/Src/Gui/XrefBrowseDialog.h b/src/gui/Src/Gui/XrefBrowseDialog.h index 5c540afe..cdd8b0e7 100644 --- a/src/gui/Src/Gui/XrefBrowseDialog.h +++ b/src/gui/Src/Gui/XrefBrowseDialog.h @@ -18,7 +18,8 @@ class XrefBrowseDialog : public QDialog, public ActionHelper public: explicit XrefBrowseDialog(QWidget* parent); ~XrefBrowseDialog(); - void setup(duint address, QString command = "disasm"); + using GotoFunction = std::function; + void setup(duint address, GotoFunction gotoFunction); private slots: void on_listWidget_itemDoubleClicked(QListWidgetItem* item); @@ -58,8 +59,8 @@ private: XREF_INFO mXrefInfo; duint mAddress; int mPrevSelectionSize; - QString mCommand; MenuBuilder* mMenu; + GotoFunction mGotoFunction; }; #endif // XREFBROWSEDIALOG_H