From 5dda6eb13a718902105d2bd4718250a27504876c Mon Sep 17 00:00:00 2001 From: torusrxxx Date: Sat, 5 Aug 2023 21:06:01 +0800 Subject: [PATCH 1/2] Add tips to some common actions --- src/gui/Src/Gui/EditFloatRegister.cpp | 116 ++++++++++++++------------ src/gui/Src/Gui/MainWindow.cpp | 2 +- src/gui/Src/Utils/ActionHelpers.h | 15 +++- src/gui/Src/Utils/CommonActions.cpp | 41 ++++++--- src/gui/Src/Utils/CommonActions.h | 6 +- 5 files changed, 109 insertions(+), 71 deletions(-) diff --git a/src/gui/Src/Gui/EditFloatRegister.cpp b/src/gui/Src/Gui/EditFloatRegister.cpp index 454a28d6..abc35849 100644 --- a/src/gui/Src/Gui/EditFloatRegister.cpp +++ b/src/gui/Src/Gui/EditFloatRegister.cpp @@ -172,65 +172,71 @@ EditFloatRegister::EditFloatRegister(int RegisterSize, QWidget* parent) : void EditFloatRegister::hideUpperPart() { - ui->line->hide(); - ui->labelH0->hide(); - ui->labelH1->hide(); - ui->labelH2->hide(); - ui->labelH3->hide(); - ui->labelH4->hide(); - ui->labelH5->hide(); - ui->labelH6->hide(); - ui->labelH7->hide(); - ui->labelH8->hide(); - ui->labelH9->hide(); - ui->labelHA->hide(); - ui->labelHB->hide(); - ui->labelHC->hide(); - ui->labelHD->hide(); - ui->labelHE->hide(); - ui->hexEdit->hide(); - ui->shortEdit0->hide(); - ui->shortEdit1->hide(); - ui->shortEdit2->hide(); - ui->shortEdit3->hide(); - ui->shortEdit4->hide(); - ui->shortEdit5->hide(); - ui->shortEdit6->hide(); - ui->shortEdit7->hide(); - ui->longEdit0->hide(); - ui->longEdit1->hide(); - ui->longEdit2->hide(); - ui->longEdit3->hide(); - ui->floatEdit0->hide(); - ui->floatEdit1->hide(); - ui->floatEdit2->hide(); - ui->floatEdit3->hide(); - ui->doubleEdit0->hide(); - ui->doubleEdit1->hide(); - ui->longLongEdit0->hide(); - ui->longLongEdit1->hide(); + QWidget* useless_controls[] = {ui->line, + ui->labelH0, + ui->labelH1, + ui->labelH2, + ui->labelH3, + ui->labelH4, + ui->labelH5, + ui->labelH6, + ui->labelH7, + ui->labelH8, + ui->labelH9, + ui->labelHA, + ui->labelHB, + ui->labelHC, + ui->labelHD, + ui->labelHE, + ui->hexEdit, + ui->shortEdit0, + ui->shortEdit1, + ui->shortEdit2, + ui->shortEdit3, + ui->shortEdit4, + ui->shortEdit5, + ui->shortEdit6, + ui->shortEdit7, + ui->longEdit0, + ui->longEdit1, + ui->longEdit2, + ui->longEdit3, + ui->floatEdit0, + ui->floatEdit1, + ui->floatEdit2, + ui->floatEdit3, + ui->doubleEdit0, + ui->doubleEdit1, + ui->longLongEdit0, + ui->longLongEdit1 + }; + for(auto all : useless_controls) + all->hide(); } void EditFloatRegister::hideNonMMXPart() { - ui->labelL4->hide(); - ui->labelL5->hide(); - ui->labelL6->hide(); - ui->labelL7->hide(); - ui->labelLC->hide(); - ui->labelLD->hide(); - ui->doubleEdit0_2->hide(); - ui->doubleEdit1_2->hide(); - ui->longLongEdit0_2->hide(); - ui->longLongEdit1_2->hide(); - ui->shortEdit4_2->hide(); - ui->shortEdit5_2->hide(); - ui->shortEdit6_2->hide(); - ui->shortEdit7_2->hide(); - ui->longEdit2_2->hide(); - ui->longEdit3_2->hide(); - ui->floatEdit2_2->hide(); - ui->floatEdit3_2->hide(); + QWidget* useless_controls[] = {ui->labelL4, + ui->labelL5, + ui->labelL6, + ui->labelL7, + ui->labelLC, + ui->labelLD, + ui->doubleEdit0_2, + ui->doubleEdit1_2, + ui->longLongEdit0_2, + ui->longLongEdit1_2, + ui->shortEdit4_2, + ui->shortEdit5_2, + ui->shortEdit6_2, + ui->shortEdit7_2, + ui->longEdit2_2, + ui->longEdit3_2, + ui->floatEdit2_2, + ui->floatEdit3_2 + }; + for(auto all : useless_controls) + all->hide(); } /** diff --git a/src/gui/Src/Gui/MainWindow.cpp b/src/gui/Src/Gui/MainWindow.cpp index 8a10354f..926a86a2 100644 --- a/src/gui/Src/Gui/MainWindow.cpp +++ b/src/gui/Src/Gui/MainWindow.cpp @@ -126,7 +126,7 @@ MainWindow::MainWindow(QWidget* parent) initMenuApi(); Bridge::getBridge()->emitMenuAddToList(this, ui->menuPlugins, GUI_PLUGIN_MENU); - // Set window title + // Set window title to executable name if(BridgeIsProcessElevated()) { mWindowMainTitle = tr("%1 [Elevated]").arg(QCoreApplication::applicationName()); diff --git a/src/gui/Src/Utils/ActionHelpers.h b/src/gui/Src/Utils/ActionHelpers.h index 1bd02ca5..acd48e40 100644 --- a/src/gui/Src/Utils/ActionHelpers.h +++ b/src/gui/Src/Utils/ActionHelpers.h @@ -1,5 +1,5 @@ #pragma once - +#include #include #include #include "Configuration.h" @@ -12,6 +12,7 @@ using MakeActionFunc1 = std::function; using MakeShortcutActionFunc1 = std::function; using MakeShortcutActionFunc2 = std::function; +using MakeShortcutDescActionFunc2 = std::function; using MakeMenuActionFunc1 = std::function; using MakeMenuActionFunc2 = std::function; using MakeShortcutMenuActionFunc1 = std::function; @@ -25,6 +26,7 @@ struct ActionHelperFuncs MakeActionFunc2 makeAction2; MakeShortcutActionFunc1 makeShortcutAction1; MakeShortcutActionFunc2 makeShortcutAction2; + MakeShortcutDescActionFunc2 makeShortcutDescAction2; MakeMenuActionFunc1 makeMenuAction1; MakeMenuActionFunc2 makeMenuAction2; MakeShortcutMenuActionFunc1 makeShortcutMenuAction1; @@ -117,6 +119,12 @@ protected: { return makeShortcutAction(icon, text, slot, shortcut); }; + funcs.makeShortcutDescAction2 = [this](const QIcon & icon, const QString & text, const QString & description, const SlotFunc & slot, const char* shortcut) + { + auto action = makeShortcutAction(icon, text, slot, shortcut); + action->setStatusTip(description); + return action; + }; funcs.makeMenuAction1 = [this](QMenu * menu, const QString & text, const SlotFunc & slot) { return makeMenuAction(menu, text, slot); @@ -260,4 +268,9 @@ protected: { return funcs.makeShortcutMenuAction2(menu, icon, text, slot, shortcut); } + + inline QAction* makeShortcutDescAction(const QIcon & icon, const QString & text, const QString & description, const SlotFunc & slot, const char* shortcut) + { + return funcs.makeShortcutDescAction2(icon, text, description, slot, shortcut); + } }; diff --git a/src/gui/Src/Utils/CommonActions.cpp b/src/gui/Src/Utils/CommonActions.cpp index 2790f0ab..749f1570 100644 --- a/src/gui/Src/Utils/CommonActions.cpp +++ b/src/gui/Src/Utils/CommonActions.cpp @@ -31,7 +31,7 @@ void CommonActions::build(MenuBuilder* builder, int actions) // Menu action if(actions & ActionDisasm) { - builder->addAction(makeShortcutAction(DIcon(ArchValue("processor32", "processor64")), tr("Follow in Disassembler"), std::bind(&CommonActions::followDisassemblySlot, this), "ActionFollowDisasm"), wIsDebugging); + builder->addAction(makeShortcutDescAction(DIcon(ArchValue("processor32", "processor64")), tr("Follow in Disassembler"), tr("Show this address in disassembler. Equivalent command \"d address\"."), std::bind(&CommonActions::followDisassemblySlot, this), "ActionFollowDisasm"), wIsDebugging); } if(actions & ActionDisasmData) { @@ -39,7 +39,7 @@ void CommonActions::build(MenuBuilder* builder, int actions) } if(actions & ActionDump) { - builder->addAction(makeCommandAction(DIcon("dump"), tr("Follow in Dump"), "dump $")); + builder->addAction(makeCommandDescAction(DIcon("dump"), tr("Follow in Dump"), tr("Show the address in dump. Equivalent command \"dump address\"."), "dump $")); } if(actions & ActionDumpData) { @@ -66,7 +66,7 @@ void CommonActions::build(MenuBuilder* builder, int actions) } if(actions & ActionStackDump) { - builder->addAction(makeCommandAction(DIcon("stack"), tr("Follow in Stack"), "sdump $", "ActionFollowStack"), [this](QMenu*) + builder->addAction(makeCommandDescAction(DIcon("stack"), tr("Follow in Stack"), tr("Show this address in stack view. Equivalent command \"sdump address\"."), "sdump $", "ActionFollowStack"), [this](QMenu*) { auto start = mGetSelection(); return (DbgMemIsValidReadPtr(start) && DbgMemFindBaseAddr(start, 0) == DbgMemFindBaseAddr(DbgValFromString("csp"), 0)); @@ -74,11 +74,11 @@ void CommonActions::build(MenuBuilder* builder, int actions) } if(actions & ActionMemoryMap) { - builder->addAction(makeCommandAction(DIcon("memmap_find_address_page"), tr("Follow in Memory Map"), "memmapdump $", "ActionFollowMemMap"), wIsDebugging); + builder->addAction(makeCommandDescAction(DIcon("memmap_find_address_page"), tr("Follow in Memory Map"), tr("Show this address in memory map view. Equivalent command \"memmapdump address\"."), "memmapdump $", "ActionFollowMemMap"), wIsDebugging); } if(actions & ActionGraph) { - builder->addAction(makeShortcutAction(DIcon("graph"), tr("Graph"), std::bind(&CommonActions::graphSlot, this), "ActionGraph")); + builder->addAction(makeShortcutDescAction(DIcon("graph"), tr("Graph"), tr("Show the control flow graph of this function in CPU view. Equivalent command \"graph address\"."), std::bind(&CommonActions::graphSlot, this), "ActionGraph")); } if(actions & ActionBreakpoint) { @@ -164,19 +164,19 @@ void CommonActions::build(MenuBuilder* builder, int actions) } if(actions & ActionBookmark) { - builder->addAction(makeShortcutAction(DIcon("bookmark_toggle"), tr("Toggle Bookmark"), std::bind(&CommonActions::setBookmarkSlot, this), "ActionToggleBookmark"), wIsDebugging); + builder->addAction(makeShortcutDescAction(DIcon("bookmark_toggle"), tr("Toggle Bookmark"), tr("Set a bookmark here, or remove bookmark. Equivalent command \"bookmarkset address\"/\"bookmarkdel address\"."), std::bind(&CommonActions::setBookmarkSlot, this), "ActionToggleBookmark"), wIsDebugging); } if(actions & ActionNewOrigin) { - builder->addAction(makeShortcutAction(DIcon("neworigin"), tr("Set %1 Here").arg(ArchValue("EIP", "RIP")), std::bind(&CommonActions::setNewOriginHereActionSlot, this), "ActionSetNewOriginHere")); + builder->addAction(makeShortcutDescAction(DIcon("neworigin"), tr("Set %1 Here").arg(ArchValue("EIP", "RIP")), tr("Set the next executed instruction to this address. Equivalent command \"mov cip, address\"."), std::bind(&CommonActions::setNewOriginHereActionSlot, this), "ActionSetNewOriginHere")); } if(actions & ActionNewThread) { - builder->addAction(makeShortcutAction(DIcon("createthread"), tr("Create New Thread Here"), std::bind(&CommonActions::createThreadSlot, this), "ActionCreateNewThreadHere")); + builder->addAction(makeShortcutDescAction(DIcon("createthread"), tr("Create New Thread Here"), tr("Create a new thread at this address. Equivalent command \"createthread address, argument\"."), std::bind(&CommonActions::createThreadSlot, this), "ActionCreateNewThreadHere")); } if(actions & ActionWatch) { - builder->addAction(makeCommandAction(DIcon("animal-dog"), ArchValue(tr("&Watch DWORD"), tr("&Watch QWORD")), "AddWatch \"[$]\", \"uint\"", "ActionWatchDwordQword")); + builder->addAction(makeCommandDescAction(DIcon("animal-dog"), ArchValue(tr("&Watch DWORD"), tr("&Watch QWORD")), tr("Add the address in the watch view. Equivalent command \"AddWatch [address], \"uint\"\"."), "AddWatch \"[$]\", \"uint\"", "ActionWatchDwordQword")); } } @@ -197,7 +197,23 @@ QAction* CommonActions::makeCommandAction(const QIcon & icon, const QString & te }); } -QWidget* CommonActions::widgetparent() +static QAction* makeDescActionHelper(QAction* action, const QString & description) +{ + action->setStatusTip(description); + return action; +} + +QAction* CommonActions::makeCommandDescAction(const QIcon & icon, const QString & text, const QString & description, const char* cmd) +{ + return makeDescActionHelper(makeCommandAction(icon, text, cmd), description); +} + +QAction* CommonActions::makeCommandDescAction(const QIcon & icon, const QString & text, const QString & description, const char* cmd, const char* shortcut) +{ + return makeDescActionHelper(makeCommandAction(icon, text, cmd, shortcut), description); +} + +QWidget* CommonActions::widgetparent() const { return dynamic_cast(parent()); } @@ -294,13 +310,14 @@ void CommonActions::setBookmarkSlot() } // Give a warning about the selected address is not executable -bool CommonActions::WarningBoxNotExecutable(const QString & text, duint wVA) +bool CommonActions::WarningBoxNotExecutable(const QString & text, duint wVA) const { if(DbgFunctions()->IsDepEnabled() && !DbgFunctions()->MemIsCodePage(wVA, false)) { - QMessageBox msgyn(QMessageBox::Warning, tr("Current address is not executable"), text, QMessageBox::Yes | QMessageBox::No, widgetparent()); + QMessageBox msgyn(QMessageBox::Warning, tr("Address %1 is not executable").arg(ToPtrString(wVA)), text, QMessageBox::Yes | QMessageBox::No, widgetparent()); msgyn.setWindowIcon(DIcon("compile-warning")); msgyn.setParent(widgetparent(), Qt::Dialog); + msgyn.setDefaultButton(QMessageBox::No); msgyn.setWindowFlags(msgyn.windowFlags() & (~Qt::WindowContextHelpButtonHint)); if(msgyn.exec() == QMessageBox::No) return false; diff --git a/src/gui/Src/Utils/CommonActions.h b/src/gui/Src/Utils/CommonActions.h index b48979a5..d7922b8e 100644 --- a/src/gui/Src/Utils/CommonActions.h +++ b/src/gui/Src/Utils/CommonActions.h @@ -52,6 +52,8 @@ public: QAction* makeCommandAction(const QIcon & icon, const QString & text, const char* cmd, const char* shortcut); QAction* makeCommandAction(const QIcon & icon, const QString & text, const char* cmd); + QAction* makeCommandDescAction(const QIcon & icon, const QString & text, const QString & description, const char* cmd); + QAction* makeCommandDescAction(const QIcon & icon, const QString & text, const QString & description, const char* cmd, const char* shortcut); public slots: void followDisassemblySlot(); void setLabelSlot(); @@ -72,6 +74,6 @@ public slots: void createThreadSlot(); private: GetSelectionFunc mGetSelection; - bool WarningBoxNotExecutable(const QString & text, duint wVA); - QWidget* widgetparent(); + bool WarningBoxNotExecutable(const QString & text, duint wVA) const; + QWidget* widgetparent() const; }; From 79830fd09383b9d76b8a742e47bdd08dce8bc356 Mon Sep 17 00:00:00 2001 From: torusrxxx Date: Sat, 5 Aug 2023 21:32:12 +0800 Subject: [PATCH 2/2] Allow go to while not debugging in trace --- src/gui/Src/Gui/GotoDialog.cpp | 9 +++++---- src/gui/Src/Gui/GotoDialog.h | 3 ++- src/gui/Src/Tracer/TraceBrowser.cpp | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/gui/Src/Gui/GotoDialog.cpp b/src/gui/Src/Gui/GotoDialog.cpp index 253671e1..68131cd8 100644 --- a/src/gui/Src/Gui/GotoDialog.cpp +++ b/src/gui/Src/Gui/GotoDialog.cpp @@ -6,11 +6,12 @@ #include "QCompleter" #include "SymbolAutoCompleteModel.h" -GotoDialog::GotoDialog(QWidget* parent, bool allowInvalidExpression, bool allowInvalidAddress) +GotoDialog::GotoDialog(QWidget* parent, bool allowInvalidExpression, bool allowInvalidAddress, bool allowNotDebugging) : QDialog(parent), ui(new Ui::GotoDialog), allowInvalidExpression(allowInvalidExpression), - allowInvalidAddress(allowInvalidAddress || allowInvalidExpression) + allowInvalidAddress(allowInvalidAddress || allowInvalidExpression), + allowNotDebugging(allowNotDebugging) { //setup UI first ui->setupUi(this); @@ -18,7 +19,7 @@ GotoDialog::GotoDialog(QWidget* parent, bool allowInvalidExpression, bool allowI setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint | Qt::MSWindowsFixedSizeDialogHint); //initialize stuff - if(!DbgIsDebugging()) //not debugging + if(!allowNotDebugging && !DbgIsDebugging()) //not debugging ui->labelError->setText(tr("Not debugging...")); else ui->labelError->setText(tr("Invalid expression...")); @@ -105,7 +106,7 @@ void GotoDialog::expressionChanged(bool validExpression, bool validPointer, dsin } if(expressionText == expression) return; - if(!DbgIsDebugging()) //not debugging + if(!allowNotDebugging && !DbgIsDebugging()) //not debugging { ui->labelError->setText(tr("Not debugging...")); setOkEnabled(false); diff --git a/src/gui/Src/Gui/GotoDialog.h b/src/gui/Src/Gui/GotoDialog.h index 4f0b4819..996ef7c3 100644 --- a/src/gui/Src/Gui/GotoDialog.h +++ b/src/gui/Src/Gui/GotoDialog.h @@ -16,7 +16,7 @@ class GotoDialog : public QDialog Q_OBJECT public: - explicit GotoDialog(QWidget* parent = 0, bool allowInvalidExpression = false, bool allowInvalidAddress = false); + explicit GotoDialog(QWidget* parent = 0, bool allowInvalidExpression = false, bool allowInvalidAddress = false, bool allowNotDebugging = false); ~GotoDialog(); QString expressionText; duint validRangeStart; @@ -25,6 +25,7 @@ public: QString modName; bool allowInvalidExpression; bool allowInvalidAddress; + bool allowNotDebugging; void showEvent(QShowEvent* event); void hideEvent(QHideEvent* event); void validateExpression(QString expression); diff --git a/src/gui/Src/Tracer/TraceBrowser.cpp b/src/gui/Src/Tracer/TraceBrowser.cpp index 4a115b2f..e0925568 100644 --- a/src/gui/Src/Tracer/TraceBrowser.cpp +++ b/src/gui/Src/Tracer/TraceBrowser.cpp @@ -1411,7 +1411,7 @@ void TraceBrowser::gotoSlot() { if(mTraceFile == nullptr || mTraceFile->Progress() < 100) return; - GotoDialog gotoDlg(this, false, true); // TODO: Cannot use when not debugging + GotoDialog gotoDlg(this, false, true, true); if(gotoDlg.exec() == QDialog::Accepted) { auto val = DbgValFromString(gotoDlg.expressionText.toUtf8().constData());