diff --git a/src/gui/Src/Gui/BreakpointsView.cpp b/src/gui/Src/Gui/BreakpointsView.cpp index 4fd0626c..0f3ab381 100644 --- a/src/gui/Src/Gui/BreakpointsView.cpp +++ b/src/gui/Src/Gui/BreakpointsView.cpp @@ -39,7 +39,7 @@ BreakpointsView::BreakpointsView(QWidget* parent) void BreakpointsView::setupContextMenu() { - mMenuBuilder = new MenuBuilder(this, [this](QMenu*) + mMenuBuilder = new MenuBuilder(this, [](QMenu*) { return DbgIsDebugging(); }); @@ -48,7 +48,14 @@ void BreakpointsView::setupContextMenu() { return isValidBp(); }; - + mMenuBuilder->addAction(makeAction(DIcon(ArchValue("processor32.png", "processor64.png")), tr("Follow breakpoint"), SLOT(followBreakpointSlot())), [this](QMenu*) + { + if(!isValidBp()) + return false; + if(selectedBp().type == bp_exception) + return false; + return true; + }); mMenuBuilder->addAction(makeShortcutAction(DIcon("breakpoint_remove.png"), tr("&Remove"), SLOT(removeBreakpointSlot()), "ActionDeleteBreakpoint"), validBp); QAction* enableDisableBreakpoint = makeShortcutAction(DIcon("breakpoint_disable.png"), tr("Disable"), SLOT(toggleBreakpointSlot()), "ActionEnableDisableBreakpoint"); mMenuBuilder->addAction(enableDisableBreakpoint, [this, enableDisableBreakpoint](QMenu*) @@ -557,10 +564,16 @@ void BreakpointsView::followBreakpointSlot() return; auto & bp = selectedBp(); if(bp.type == bp_exception || !bp.active) + { + GuiAddStatusBarMessage(tr("Cannot follow this breakpoint.\n").toUtf8().constData()); return; + } duint addr = bp.type == bp_dll ? DbgModBaseFromName(bp.mod) : bp.addr; if(!DbgMemIsValidReadPtr(addr)) + { + GuiAddStatusBarMessage(tr("Cannot follow this breakpoint.\n").toUtf8().constData()); return; + } if(DbgFunctions()->MemIsCodePage(addr, false)) DbgCmdExecDirect(QString("disasm %1").arg(ToPtrString(addr))); else diff --git a/src/gui/Src/Gui/CPUDisassembly.cpp b/src/gui/Src/Gui/CPUDisassembly.cpp index ed87c2e6..bb2d18a8 100644 --- a/src/gui/Src/Gui/CPUDisassembly.cpp +++ b/src/gui/Src/Gui/CPUDisassembly.cpp @@ -311,7 +311,7 @@ void CPUDisassembly::setupRightClickContextMenu() { return rvaToVa(getInitialSelection()); }); - mCommonActions->build(mMenuBuilder, CommonActions::ActionBreakpoint | CommonActions::ActionMemoryMap | CommonActions::ActionComment | CommonActions::ActionBookmark); + mCommonActions->build(mMenuBuilder, CommonActions::ActionBreakpoint | CommonActions::ActionMemoryMap | CommonActions::ActionGraph | CommonActions::ActionComment | CommonActions::ActionBookmark); mMenuBuilder->addMenu(makeMenu(DIcon("dump.png"), tr("&Follow in Dump")), [this](QMenu * menu) { @@ -332,8 +332,6 @@ void CPUDisassembly::setupRightClickContextMenu() return DbgFunctions()->GetSourceFromAddr(rvaToVa(getInitialSelection()), 0, 0); }); - mMenuBuilder->addAction(makeShortcutAction(DIcon("graph.png"), tr("Graph"), SLOT(graphSlot()), "ActionGraph")); - mMenuBuilder->addMenu(makeMenu(DIcon("help.png"), tr("Help on Symbolic Name")), [this](QMenu * menu) { QSet labels; @@ -1902,12 +1900,6 @@ void CPUDisassembly::setEncodeTypeSlot() GuiUpdateDisassemblyView(); } -void CPUDisassembly::graphSlot() -{ - if(DbgCmdExecDirect(QString("graph %1").arg(ToPtrString(rvaToVa(getSelectionStart()))).toUtf8().constData())) - GuiFocusView(GUI_GRAPH); -} - void CPUDisassembly::analyzeModuleSlot() { DbgCmdExec("cfanal"); diff --git a/src/gui/Src/Gui/CPUDisassembly.h b/src/gui/Src/Gui/CPUDisassembly.h index c2eba4a5..3f326d6a 100644 --- a/src/gui/Src/Gui/CPUDisassembly.h +++ b/src/gui/Src/Gui/CPUDisassembly.h @@ -105,7 +105,6 @@ public slots: void removeAnalysisModuleSlot(); void setEncodeTypeSlot(); void setEncodeTypeRangeSlot(); - void graphSlot(); void analyzeModuleSlot(); void copyTokenTextSlot(); void copyTokenValueSlot(); diff --git a/src/gui/Src/Gui/CPUDump.cpp b/src/gui/Src/Gui/CPUDump.cpp index 954c1444..cde3dc0d 100644 --- a/src/gui/Src/Gui/CPUDump.cpp +++ b/src/gui/Src/Gui/CPUDump.cpp @@ -81,8 +81,8 @@ void CPUDump::setupContextMenu() return DbgFunctions()->PatchInRange(rvaToVa(getSelectionStart()), rvaToVa(getSelectionEnd())); }); - mCommonActions->build(mMenuBuilder, CommonActions::ActionDisasm | CommonActions::ActionMemoryMap | CommonActions::ActionDumpData | CommonActions::ActionDisasmData - | CommonActions::ActionStackDump | CommonActions::ActionLabel | CommonActions::ActionWatch); + mCommonActions->build(mMenuBuilder, CommonActions::ActionDisasm | CommonActions::ActionMemoryMap | CommonActions::ActionDumpData | CommonActions::ActionDumpN + | CommonActions::ActionDisasmData | CommonActions::ActionStackDump | CommonActions::ActionLabel | CommonActions::ActionWatch); auto wIsValidReadPtrCallback = [this](QMenu*) { duint ptr = 0; @@ -90,24 +90,6 @@ void CPUDump::setupContextMenu() return DbgMemIsValidReadPtr(ptr); }; - MenuBuilder* wFollowInDumpMenu = new MenuBuilder(this, [wIsValidReadPtrCallback, this](QMenu * menu) - { - if(!wIsValidReadPtrCallback(menu)) - return false; - QList tabNames; - mMultiDump->getTabNames(tabNames); - for(int i = 0; i < tabNames.length(); i++) - mFollowInDumpActions[i]->setText(tabNames[i]); - return true; - }); - int maxDumps = mMultiDump->getMaxCPUTabs(); - for(int i = 0; i < maxDumps; i++) - { - QAction* action = makeAction(DIcon("dump.png"), QString(), SLOT(followInDumpNSlot())); - wFollowInDumpMenu->addAction(action); - mFollowInDumpActions.push_back(action); - } - mMenuBuilder->addMenu(makeMenu(DIcon("dump.png"), ArchValue(tr("&Follow DWORD in Dump"), tr("&Follow QWORD in Dump"))), wFollowInDumpMenu); mMenuBuilder->addAction(makeShortcutAction(DIcon("modify.png"), tr("&Modify Value"), SLOT(modifyValueSlot()), "ActionModifyValue"), [this](QMenu*) { return getSizeOf(mDescriptor.at(0).data.itemSize) <= sizeof(duint); @@ -1483,13 +1465,6 @@ void CPUDump::syncWithExpressionSlot() updateDumpSlot(); } -void CPUDump::followInDumpNSlot() -{ - for(int i = 0; i < mFollowInDumpActions.length(); i++) - if(mFollowInDumpActions[i] == sender()) - DbgCmdExec(QString("dump \"[%1]\", \"%2\"").arg(ToPtrString(rvaToVa(getSelectionStart()))).arg(i + 1)); -} - void CPUDump::allocMemorySlot() { WordEditDialog mLineEdit(this); diff --git a/src/gui/Src/Gui/CPUDump.h b/src/gui/Src/Gui/CPUDump.h index e820e623..2b65612b 100644 --- a/src/gui/Src/Gui/CPUDump.h +++ b/src/gui/Src/Gui/CPUDump.h @@ -81,7 +81,6 @@ public slots: void selectionUpdatedSlot(); void syncWithExpressionSlot(); - void followInDumpNSlot(); void allocMemorySlot(); void headerButtonReleasedSlot(int colIndex); diff --git a/src/gui/Src/Gui/CPUStack.cpp b/src/gui/Src/Gui/CPUStack.cpp index 53e8467b..80d00c19 100644 --- a/src/gui/Src/Gui/CPUStack.cpp +++ b/src/gui/Src/Gui/CPUStack.cpp @@ -282,22 +282,7 @@ void CPUStack::setupContextMenu() //Follow PTR in Dump auto followDumpName = ArchValue(tr("Follow DWORD in &Dump"), tr("Follow QWORD in &Dump")); - //Follow in Dump N menu - auto followDumpNMenu = new MenuBuilder(this, [this](QMenu*) - { - duint ptr; - return DbgMemRead(rvaToVa(getInitialSelection()), (unsigned char*)&ptr, sizeof(ptr)) && DbgMemIsValidReadPtr(ptr); - }); - int maxDumps = mMultiDump->getMaxCPUTabs(); - for(int i = 0; i < maxDumps; i++) - { - auto action = makeAction(tr("Dump %1").arg(i + 1), SLOT(followinDumpNSlot())); - followDumpNMenu->addAction(action); - mFollowInDumpActions.push_back(action); - } - mMenuBuilder->addMenu(makeMenu(DIcon("dump.png"), followDumpName.replace("&", "")), followDumpNMenu); - - mCommonActions->build(mMenuBuilder, CommonActions::ActionWatch); + mCommonActions->build(mMenuBuilder, CommonActions::ActionDumpN | CommonActions::ActionWatch); mPluginMenu = new QMenu(this); Bridge::getBridge()->emitMenuAddToList(this, mPluginMenu, GUI_STACK_MENU); @@ -721,23 +706,6 @@ void CPUStack::followDisasmSlot() } } -void CPUStack::followinDumpNSlot() -{ - duint selectedData = rvaToVa(getInitialSelection()); - - if(DbgMemIsValidReadPtr(selectedData)) - { - for(int i = 0; i < mFollowInDumpActions.length(); i++) - { - if(mFollowInDumpActions[i] == sender()) - { - QString addrText = QString("%1").arg(ToPtrString(selectedData)); - DbgCmdExec(QString("dump [%1], %2").arg(addrText.toUtf8().constData()).arg(i + 1)); - } - } - } -} - void CPUStack::followStackSlot() { duint selectedData; diff --git a/src/gui/Src/Gui/CPUStack.h b/src/gui/Src/Gui/CPUStack.h index 01c72ec4..de3a9588 100644 --- a/src/gui/Src/Gui/CPUStack.h +++ b/src/gui/Src/Gui/CPUStack.h @@ -42,7 +42,6 @@ public slots: void selectionSet(const SELECTIONDATA* selection); void selectionUpdatedSlot(); void followDisasmSlot(); - void followinDumpNSlot(); void followStackSlot(); void binaryEditSlot(); void binaryFillSlot(); @@ -64,7 +63,6 @@ private: QAction* mFreezeStack; QAction* mFollowStack; QAction* mFollowDisasm; - QList mFollowInDumpActions; QMenu* mPluginMenu; GotoDialog* mGoto; diff --git a/src/gui/Src/Gui/CPUWidget.cpp b/src/gui/Src/Gui/CPUWidget.cpp index 7fcc3abc..75ef37a2 100644 --- a/src/gui/Src/Gui/CPUWidget.cpp +++ b/src/gui/Src/Gui/CPUWidget.cpp @@ -58,7 +58,7 @@ CPUWidget::CPUWidget(QWidget* parent) : QWidget(parent), ui(new Ui::CPUWidget) connect(mDisas, SIGNAL(selectionChanged(dsint)), mInfo, SLOT(disasmSelectionChanged(dsint))); - mDump = new CPUMultiDump(mDisas, 5, 0); //dump widget + mDump = new CPUMultiDump(mDisas, 5, this); //dump widget ui->mBotLeftFrameLayout->addWidget(mDump); mGeneralRegs = new CPURegistersView(this); diff --git a/src/gui/Src/Utils/CommonActions.cpp b/src/gui/Src/Utils/CommonActions.cpp index 41ee53f5..4ecb9f10 100644 --- a/src/gui/Src/Utils/CommonActions.cpp +++ b/src/gui/Src/Utils/CommonActions.cpp @@ -45,6 +45,25 @@ void CommonActions::build(MenuBuilder* builder, int actions) { builder->addAction(makeCommandAction(DIcon("dump.png"), ArchValue(tr("&Follow DWORD in Current Dump"), tr("&Follow QWORD in Current Dump")), "dump [$]", "ActionFollowDwordQwordDump"), wIsValidReadPtrCallback); } + if(actions & ActionDumpN) + { + //Follow in Dump N menu + MenuBuilder* followDumpNMenu = new MenuBuilder(this, [this](QMenu*) + { + duint ptr; + return DbgMemRead(mGetSelection(), (unsigned char*)&ptr, sizeof(ptr)) && DbgMemIsValidReadPtr(ptr); + }); + const int maxDumps = 5; // TODO: get this value from CPUMultiDump + for(int i = 0; i < maxDumps; i++) + // TODO: Get dump tab names + followDumpNMenu->addAction(makeAction(tr("Dump %1").arg(i + 1), [i, this] + { + duint selectedData = mGetSelection(); + if(DbgMemIsValidReadPtr(selectedData)) + DbgCmdExec(QString("dump [%1], %2").arg(ToPtrString(selectedData)).arg(i + 1)); + })); + builder->addMenu(makeMenu(DIcon("dump.png"), ArchValue(tr("Follow DWORD in Dump"), tr("Follow QWORD in Dump"))), followDumpNMenu); + } if(actions & ActionStackDump) { builder->addAction(makeCommandAction(DIcon("stack.png"), tr("Follow in Stack"), "sdump $", "ActionFollowStack"), [this](QMenu*) @@ -57,6 +76,10 @@ void CommonActions::build(MenuBuilder* builder, int actions) { builder->addAction(makeCommandAction(DIcon("memmap_find_address_page.png"), tr("Follow in Memory Map"), "memmapdump $", "ActionFollowMemMap"), wIsDebugging); } + if(actions & ActionGraph) + { + builder->addAction(makeShortcutAction(DIcon("graph.png"), tr("Graph"), std::bind(&CommonActions::graphSlot, this), "ActionGraph")); + } if(actions & ActionBreakpoint) { QAction* toggleBreakpointAction = makeShortcutAction(DIcon("breakpoint_toggle.png"), tr("Toggle"), std::bind(&CommonActions::toggleInt3BPActionSlot, this), "ActionToggleBreakpoint"); @@ -66,10 +89,11 @@ void CommonActions::build(MenuBuilder* builder, int actions) QMenu* replaceSlotMenu = makeMenu(DIcon("breakpoint_execute.png"), tr("Set Hardware on Execution")); // Replacement slot menu are only used when the breakpoints are full, so using "Unknown" as the placeholder. Might want to change this in case we display the menu when there are still free slots. - QAction* replaceSlot0Action = makeMenuAction(replaceSlotMenu, DIcon("breakpoint_execute_slot1.png"), tr("Replace Slot 0 (Unknown)"), std::bind(&CommonActions::setHwBpOnSlot0ActionSlot, this)); - QAction* replaceSlot1Action = makeMenuAction(replaceSlotMenu, DIcon("breakpoint_execute_slot2.png"), tr("Replace Slot 1 (Unknown)"), std::bind(&CommonActions::setHwBpOnSlot1ActionSlot, this)); - QAction* replaceSlot2Action = makeMenuAction(replaceSlotMenu, DIcon("breakpoint_execute_slot3.png"), tr("Replace Slot 2 (Unknown)"), std::bind(&CommonActions::setHwBpOnSlot2ActionSlot, this)); - QAction* replaceSlot3Action = makeMenuAction(replaceSlotMenu, DIcon("breakpoint_execute_slot4.png"), tr("Replace Slot 3 (Unknown)"), std::bind(&CommonActions::setHwBpOnSlot3ActionSlot, this)); + QAction* replaceSlotAction[4]; + replaceSlotAction[0] = makeMenuAction(replaceSlotMenu, DIcon("breakpoint_execute_slot1.png"), tr("Replace Slot %1 (Unknown)").arg(1), std::bind(&CommonActions::setHwBpOnSlot0ActionSlot, this)); + replaceSlotAction[1] = makeMenuAction(replaceSlotMenu, DIcon("breakpoint_execute_slot2.png"), tr("Replace Slot %1 (Unknown)").arg(2), std::bind(&CommonActions::setHwBpOnSlot1ActionSlot, this)); + replaceSlotAction[2] = makeMenuAction(replaceSlotMenu, DIcon("breakpoint_execute_slot3.png"), tr("Replace Slot %1 (Unknown)").arg(3), std::bind(&CommonActions::setHwBpOnSlot2ActionSlot, this)); + replaceSlotAction[3] = makeMenuAction(replaceSlotMenu, DIcon("breakpoint_execute_slot4.png"), tr("Replace Slot %1 (Unknown)").arg(4), std::bind(&CommonActions::setHwBpOnSlot3ActionSlot, this)); builder->addMenu(makeMenu(DIcon("breakpoint.png"), tr("Breakpoint")), [ = ](QMenu * menu) { @@ -108,25 +132,9 @@ void CommonActions::build(MenuBuilder* builder, int actions) { for(int i = 0; i < bpList.count; i++) { - if(bpList.bp[i].enabled) + if(bpList.bp[i].enabled && bpList.bp[i].slot < 4) { - switch(bpList.bp[i].slot) - { - case 0: - replaceSlot0Action->setText(tr("Replace Slot %1 (0x%2)").arg(1).arg(ToPtrString(bpList.bp[i].addr))); - break; - case 1: - replaceSlot1Action->setText(tr("Replace Slot %1 (0x%2)").arg(2).arg(ToPtrString(bpList.bp[i].addr))); - break; - case 2: - replaceSlot2Action->setText(tr("Replace Slot %1 (0x%2)").arg(3).arg(ToPtrString(bpList.bp[i].addr))); - break; - case 3: - replaceSlot3Action->setText(tr("Replace Slot %1 (0x%2)").arg(4).arg(ToPtrString(bpList.bp[i].addr))); - break; - default: - break; - } + replaceSlotAction[bpList.bp[i].slot]->setText(tr("Replace Slot %1 (0x%2)").arg(bpList.bp[i].slot + 1).arg(ToPtrString(bpList.bp[i].addr))); } } menu->addMenu(replaceSlotMenu); @@ -165,6 +173,7 @@ void CommonActions::build(MenuBuilder* builder, int actions) QAction* CommonActions::makeCommandAction(const QIcon & icon, const QString & text, const char* cmd, const char* shortcut) { + // sender() doesn't work in slots return makeShortcutAction(icon, text, [cmd, this]() { DbgCmdExec(QString(cmd).replace("$", ToPtrString(mGetSelection()))); @@ -268,10 +277,7 @@ void CommonActions::setBookmarkSlot() return; duint wVA = mGetSelection(); bool result; - if(DbgGetBookmarkAt(wVA)) - result = DbgSetBookmarkAt(wVA, false); - else - result = DbgSetBookmarkAt(wVA, true); + result = DbgSetBookmarkAt(wVA, !DbgGetBookmarkAt(wVA)); if(!result) SimpleErrorBox(widgetparent(), tr("Error!"), tr("DbgSetBookmarkAt failed!")); GuiUpdateAllViews(); @@ -407,6 +413,12 @@ void CommonActions::setHwBpAt(duint va, int slot) BridgeFree(wBPList.bp); } +void CommonActions::graphSlot() +{ + if(DbgCmdExecDirect(QString("graph %1").arg(ToPtrString(mGetSelection())))) + GuiFocusView(GUI_GRAPH); +} + void CommonActions::setNewOriginHereActionSlot() { if(!DbgIsDebugging()) diff --git a/src/gui/Src/Utils/CommonActions.h b/src/gui/Src/Utils/CommonActions.h index 0f1eada3..413844d4 100644 --- a/src/gui/Src/Utils/CommonActions.h +++ b/src/gui/Src/Utils/CommonActions.h @@ -68,6 +68,7 @@ public slots: void setHwBpOnSlot3ActionSlot(); void setHwBpAt(duint va, int slot); + void graphSlot(); void setNewOriginHereActionSlot(); void createThreadSlot(); private: