From e034a010a9347b15db42eacb7d7a33d67dbcdbcb Mon Sep 17 00:00:00 2001 From: "Thomas (nezza-_-) Roth" Date: Sun, 10 Dec 2017 21:40:15 +0100 Subject: [PATCH] Fix #136: Add a 'Create function' right click. (#202) * Fix #136: Add a 'Create function' right click. * cutter: Filter function names. --- src/cutter.cpp | 14 ++++ src/cutter.h | 3 + src/menus/DisassemblyContextMenu.cpp | 109 +++++++++++++-------------- src/menus/DisassemblyContextMenu.h | 12 ++- 4 files changed, 82 insertions(+), 56 deletions(-) diff --git a/src/cutter.cpp b/src/cutter.cpp index b9568b51..3ff56bf3 100644 --- a/src/cutter.cpp +++ b/src/cutter.cpp @@ -665,6 +665,20 @@ QString CutterCore::cmdFunctionAt(RVA addr) return cmdFunctionAt(QString::number(addr)); } +QString CutterCore::createFunctionAt(RVA addr, QString name) +{ + name.remove(QRegExp("[^a-zA-Z0-9_]")); + QString command = "af " + name + " " + RAddressString(addr); + QString ret = cmd(command); + emit refreshAll(); + return ret; +} + +void CutterCore::markString(RVA addr) +{ + cmd("Cs @" + RAddressString(addr)); +} + int CutterCore::get_size() { CORE_LOCK(); diff --git a/src/cutter.h b/src/cutter.h index 4f479936..4ef4c02c 100644 --- a/src/cutter.h +++ b/src/cutter.h @@ -252,6 +252,9 @@ public: QString cmdFunctionAt(QString addr); QString cmdFunctionAt(RVA addr); + QString createFunctionAt(RVA addr, QString name); + void markString(RVA addr); + /* SDB */ QList sdbList(QString path); QList sdbListKeys(QString path); diff --git a/src/menus/DisassemblyContextMenu.cpp b/src/menus/DisassemblyContextMenu.cpp index c419260a..6f34f023 100644 --- a/src/menus/DisassemblyContextMenu.cpp +++ b/src/menus/DisassemblyContextMenu.cpp @@ -14,6 +14,7 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent) actionCopy(this), actionAddComment(this), actionAddFlag(this), + actionCreateFunction(this), actionRename(this), actionRenameUsedHere(this), actionXRefs(this), @@ -27,26 +28,13 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent) actionSetBaseSyscall(this), actionSetBaseString(this) { - actionCopy.setText(tr("Copy")); - this->addAction(&actionCopy); - actionCopy.setShortcut(getCopySequence()); + createAction(&actionCopy, tr("Copy"), getCopySequence(), SLOT(on_actionCopy_triggered())); copySeparator = addSeparator(); - - actionAddComment.setText(tr("Add Comment")); - this->addAction(&actionAddComment); - actionAddComment.setShortcut(getCommentSequence()); - - actionAddFlag.setText(tr("Add Flag")); - this->addAction(&actionAddFlag); - actionAddFlag.setShortcut(getAddFlagSequence()); - - actionRename.setText(tr("Rename")); - this->addAction(&actionRename); - actionRename.setShortcut(getRenameSequence()); - - actionRenameUsedHere.setText(("Rename Flag/Fcn/Var Used Here")); - this->addAction(&actionRenameUsedHere); - actionRenameUsedHere.setShortcut(getRenameUsedHereSequence()); + createAction(&actionAddComment, tr("Add Comment"), getCommentSequence(), SLOT(on_actionAddComment_triggered())); + createAction(&actionAddFlag, tr("Add Flag"), getAddFlagSequence(), SLOT(on_actionAddFlag_triggered())); + createAction(&actionCreateFunction, tr("Create Function"), {}, SLOT(on_actionCreateFunction_triggered())); + createAction(&actionRename, tr("Rename"), getRenameSequence(), SLOT(on_actionRename_triggered())); + createAction(&actionRenameUsedHere, "Rename Flag/Fcn/Var Used Here", getRenameUsedHereSequence(), SLOT(on_actionRenameUsedHere_triggered())); setBaseMenu = new QMenu(tr("Set Immediate Base to..."), this); setBaseMenuAction = addMenu(setBaseMenu); @@ -66,41 +54,9 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent) setBaseMenu->addAction(&actionSetBaseSyscall); actionSetBaseString.setText(tr("String")); setBaseMenu->addAction(&actionSetBaseString); - - this->addSeparator(); - actionXRefs.setText(tr("Show X-Refs")); - this->addAction(&actionXRefs); - actionXRefs.setShortcut(getXRefSequence()); - - this->addSeparator(); - actionDisplayOptions.setText(tr("Show Options")); - actionDisplayOptions.setShortcut(getDisplayOptionsSequence()); - this->addAction(&actionDisplayOptions); - - auto pWidget = parentWidget(); - -#define ADD_SHORTCUT(sequence, slot) { \ - QShortcut *shortcut = new QShortcut((sequence), pWidget); \ - shortcut->setContext(Qt::WidgetWithChildrenShortcut); \ - connect(shortcut, &QShortcut::activated, this, (slot)); \ -} - ADD_SHORTCUT(getCopySequence(), &DisassemblyContextMenu::on_actionCopy_triggered); - ADD_SHORTCUT(getDisplayOptionsSequence(), &DisassemblyContextMenu::on_actionDisplayOptions_triggered); - ADD_SHORTCUT(getXRefSequence(), &DisassemblyContextMenu::on_actionXRefs_triggered); - ADD_SHORTCUT(getCommentSequence(), &DisassemblyContextMenu::on_actionAddComment_triggered); - ADD_SHORTCUT(getAddFlagSequence(), &DisassemblyContextMenu::on_actionAddFlag_triggered); - ADD_SHORTCUT(getRenameSequence(), &DisassemblyContextMenu::on_actionRename_triggered); - ADD_SHORTCUT(getRenameUsedHereSequence(), &DisassemblyContextMenu::on_actionRenameUsedHere_triggered); -#undef ADD_SHORTCUT - - connect(&actionCopy, SIGNAL(triggered(bool)), this, SLOT(on_actionCopy_triggered())); - - connect(&actionAddComment, SIGNAL(triggered(bool)), this, SLOT(on_actionAddComment_triggered())); - connect(&actionAddFlag, SIGNAL(triggered(bool)), this, SLOT(on_actionAddFlag_triggered())); - connect(&actionRename, SIGNAL(triggered(bool)), this, SLOT(on_actionRename_triggered())); - connect(&actionRenameUsedHere, SIGNAL(triggered(bool)), this, SLOT(on_actionRenameUsedHere_triggered())); - connect(&actionXRefs, SIGNAL(triggered(bool)), this, SLOT(on_actionXRefs_triggered())); - connect(&actionDisplayOptions, SIGNAL(triggered()), this, SLOT(on_actionDisplayOptions_triggered())); + addSeparator(); + createAction(&actionXRefs, tr("Show X-Refs"), getXRefSequence(), SLOT(on_actionXRefs_triggered())); + createAction(&actionDisplayOptions, tr("Show Options"), getDisplayOptionsSequence(), SLOT(on_actionDisplayOptions_triggered())); connect(&actionSetBaseBinary, SIGNAL(triggered(bool)), this, SLOT(on_actionSetBaseBinary_triggered())); connect(&actionSetBaseOctal, SIGNAL(triggered(bool)), this, SLOT(on_actionSetBaseOctal_triggered())); @@ -114,6 +70,14 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent) connect(this, SIGNAL(aboutToShow()), this, SLOT(aboutToShowSlot())); } +DisassemblyContextMenu::~DisassemblyContextMenu() +{ + for(QAction *action : anonymousActions) + { + delete action; + } +} + void DisassemblyContextMenu::setOffset(RVA offset) { this->offset = offset; @@ -149,8 +113,10 @@ void DisassemblyContextMenu::aboutToShowSlot() RCore *core = Core()->core(); RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, offset, R_ANAL_FCN_TYPE_NULL); RFlagItem *f = r_flag_get_i (core->flags, offset); + actionCreateFunction.setVisible(true); if (fcn) { + actionCreateFunction.setVisible(false); actionRename.setVisible(true); actionRename.setText(tr("Rename function \"%1\"").arg(fcn->name)); } @@ -194,7 +160,8 @@ QKeySequence DisassemblyContextMenu::getCopySequence() const QKeySequence DisassemblyContextMenu::getCommentSequence() const { - return {";"}; +// return {";"}; + return {}; } QKeySequence DisassemblyContextMenu::getAddFlagSequence() const @@ -258,6 +225,17 @@ void DisassemblyContextMenu::on_actionAddComment_triggered() } } +void DisassemblyContextMenu::on_actionCreateFunction_triggered() +{ + RenameDialog *dialog = new RenameDialog(this); + dialog->setWindowTitle(tr("Add function at %1").arg(RAddressString(offset))); + if(dialog->exec()) + { + QString function_name = dialog->getName(); + Core()->createFunctionAt(offset, function_name); + } +} + void DisassemblyContextMenu::on_actionAddFlag_triggered() { FlagDialog *dialog = new FlagDialog(offset, this->parentWidget()); @@ -403,3 +381,24 @@ void DisassemblyContextMenu::on_actionSetBaseString_triggered() { Core()->setImmediateBase("s", offset); } + +void DisassemblyContextMenu::createAction(QString name, QKeySequence keySequence, const char *slot) +{ + QAction *action = new QAction(this); + anonymousActions.append(action); + createAction(action, name, keySequence, slot); +} + +void DisassemblyContextMenu::createAction(QAction *action, QString name, QKeySequence keySequence, const char *slot) +{ + action->setText(name); + addAction(action); + action->setShortcut(keySequence); + + connect(action, SIGNAL(triggered(bool)), this, slot); + + auto pWidget = parentWidget(); + QShortcut *shortcut = new QShortcut(keySequence, pWidget); + shortcut->setContext(Qt::WidgetWithChildrenShortcut); + connect(shortcut, SIGNAL(activated()), this, slot); +} diff --git a/src/menus/DisassemblyContextMenu.h b/src/menus/DisassemblyContextMenu.h index b2b053c9..a9a84b14 100644 --- a/src/menus/DisassemblyContextMenu.h +++ b/src/menus/DisassemblyContextMenu.h @@ -11,7 +11,7 @@ Q_OBJECT public: DisassemblyContextMenu(QWidget *parent = nullptr); - ~DisassemblyContextMenu() = default; + ~DisassemblyContextMenu(); signals: void copy(); @@ -26,6 +26,7 @@ private slots: void on_actionCopy_triggered(); void on_actionAddComment_triggered(); + void on_actionCreateFunction_triggered(); void on_actionAddFlag_triggered(); void on_actionRename_triggered(); void on_actionRenameUsedHere_triggered(); @@ -53,11 +54,16 @@ private: RVA offset; bool canCopy; + QList anonymousActions; + QAction actionCopy; QAction *copySeparator; + + QAction actionAddComment; QAction actionAddFlag; + QAction actionCreateFunction; QAction actionRename; QAction actionRenameUsedHere; QAction actionXRefs; @@ -73,5 +79,9 @@ private: QAction actionSetBaseIPAddr; QAction actionSetBaseSyscall; QAction actionSetBaseString; + + // For creating anonymous entries (that are always visible) + void createAction(QString name, QKeySequence keySequence, const char *slot); + void createAction(QAction *action, QString name, QKeySequence keySequence, const char *slot); }; #endif // DISASSEMBLYCONTEXTMENU_H