Fix #136: Add a 'Create function' right click. (#202)

* Fix #136: Add a 'Create function' right click.

* cutter: Filter function names.
This commit is contained in:
Thomas (nezza-_-) Roth 2017-12-10 21:40:15 +01:00 committed by Maijin
parent 4a3371873a
commit e034a010a9
4 changed files with 82 additions and 56 deletions

View File

@ -665,6 +665,20 @@ QString CutterCore::cmdFunctionAt(RVA addr)
return cmdFunctionAt(QString::number(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() int CutterCore::get_size()
{ {
CORE_LOCK(); CORE_LOCK();

View File

@ -252,6 +252,9 @@ public:
QString cmdFunctionAt(QString addr); QString cmdFunctionAt(QString addr);
QString cmdFunctionAt(RVA addr); QString cmdFunctionAt(RVA addr);
QString createFunctionAt(RVA addr, QString name);
void markString(RVA addr);
/* SDB */ /* SDB */
QList<QString> sdbList(QString path); QList<QString> sdbList(QString path);
QList<QString> sdbListKeys(QString path); QList<QString> sdbListKeys(QString path);

View File

@ -14,6 +14,7 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent)
actionCopy(this), actionCopy(this),
actionAddComment(this), actionAddComment(this),
actionAddFlag(this), actionAddFlag(this),
actionCreateFunction(this),
actionRename(this), actionRename(this),
actionRenameUsedHere(this), actionRenameUsedHere(this),
actionXRefs(this), actionXRefs(this),
@ -27,26 +28,13 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent)
actionSetBaseSyscall(this), actionSetBaseSyscall(this),
actionSetBaseString(this) actionSetBaseString(this)
{ {
actionCopy.setText(tr("Copy")); createAction(&actionCopy, tr("Copy"), getCopySequence(), SLOT(on_actionCopy_triggered()));
this->addAction(&actionCopy);
actionCopy.setShortcut(getCopySequence());
copySeparator = addSeparator(); copySeparator = addSeparator();
createAction(&actionAddComment, tr("Add Comment"), getCommentSequence(), SLOT(on_actionAddComment_triggered()));
actionAddComment.setText(tr("Add Comment")); createAction(&actionAddFlag, tr("Add Flag"), getAddFlagSequence(), SLOT(on_actionAddFlag_triggered()));
this->addAction(&actionAddComment); createAction(&actionCreateFunction, tr("Create Function"), {}, SLOT(on_actionCreateFunction_triggered()));
actionAddComment.setShortcut(getCommentSequence()); createAction(&actionRename, tr("Rename"), getRenameSequence(), SLOT(on_actionRename_triggered()));
createAction(&actionRenameUsedHere, "Rename Flag/Fcn/Var Used Here", getRenameUsedHereSequence(), SLOT(on_actionRenameUsedHere_triggered()));
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());
setBaseMenu = new QMenu(tr("Set Immediate Base to..."), this); setBaseMenu = new QMenu(tr("Set Immediate Base to..."), this);
setBaseMenuAction = addMenu(setBaseMenu); setBaseMenuAction = addMenu(setBaseMenu);
@ -66,41 +54,9 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent)
setBaseMenu->addAction(&actionSetBaseSyscall); setBaseMenu->addAction(&actionSetBaseSyscall);
actionSetBaseString.setText(tr("String")); actionSetBaseString.setText(tr("String"));
setBaseMenu->addAction(&actionSetBaseString); setBaseMenu->addAction(&actionSetBaseString);
addSeparator();
this->addSeparator(); createAction(&actionXRefs, tr("Show X-Refs"), getXRefSequence(), SLOT(on_actionXRefs_triggered()));
actionXRefs.setText(tr("Show X-Refs")); createAction(&actionDisplayOptions, tr("Show Options"), getDisplayOptionsSequence(), SLOT(on_actionDisplayOptions_triggered()));
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()));
connect(&actionSetBaseBinary, SIGNAL(triggered(bool)), this, SLOT(on_actionSetBaseBinary_triggered())); connect(&actionSetBaseBinary, SIGNAL(triggered(bool)), this, SLOT(on_actionSetBaseBinary_triggered()));
connect(&actionSetBaseOctal, SIGNAL(triggered(bool)), this, SLOT(on_actionSetBaseOctal_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())); connect(this, SIGNAL(aboutToShow()), this, SLOT(aboutToShowSlot()));
} }
DisassemblyContextMenu::~DisassemblyContextMenu()
{
for(QAction *action : anonymousActions)
{
delete action;
}
}
void DisassemblyContextMenu::setOffset(RVA offset) void DisassemblyContextMenu::setOffset(RVA offset)
{ {
this->offset = offset; this->offset = offset;
@ -149,8 +113,10 @@ void DisassemblyContextMenu::aboutToShowSlot()
RCore *core = Core()->core(); RCore *core = Core()->core();
RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, offset, R_ANAL_FCN_TYPE_NULL); RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, offset, R_ANAL_FCN_TYPE_NULL);
RFlagItem *f = r_flag_get_i (core->flags, offset); RFlagItem *f = r_flag_get_i (core->flags, offset);
actionCreateFunction.setVisible(true);
if (fcn) if (fcn)
{ {
actionCreateFunction.setVisible(false);
actionRename.setVisible(true); actionRename.setVisible(true);
actionRename.setText(tr("Rename function \"%1\"").arg(fcn->name)); actionRename.setText(tr("Rename function \"%1\"").arg(fcn->name));
} }
@ -194,7 +160,8 @@ QKeySequence DisassemblyContextMenu::getCopySequence() const
QKeySequence DisassemblyContextMenu::getCommentSequence() const QKeySequence DisassemblyContextMenu::getCommentSequence() const
{ {
return {";"}; // return {";"};
return {};
} }
QKeySequence DisassemblyContextMenu::getAddFlagSequence() const 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() void DisassemblyContextMenu::on_actionAddFlag_triggered()
{ {
FlagDialog *dialog = new FlagDialog(offset, this->parentWidget()); FlagDialog *dialog = new FlagDialog(offset, this->parentWidget());
@ -403,3 +381,24 @@ void DisassemblyContextMenu::on_actionSetBaseString_triggered()
{ {
Core()->setImmediateBase("s", offset); 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);
}

View File

@ -11,7 +11,7 @@ Q_OBJECT
public: public:
DisassemblyContextMenu(QWidget *parent = nullptr); DisassemblyContextMenu(QWidget *parent = nullptr);
~DisassemblyContextMenu() = default; ~DisassemblyContextMenu();
signals: signals:
void copy(); void copy();
@ -26,6 +26,7 @@ private slots:
void on_actionCopy_triggered(); void on_actionCopy_triggered();
void on_actionAddComment_triggered(); void on_actionAddComment_triggered();
void on_actionCreateFunction_triggered();
void on_actionAddFlag_triggered(); void on_actionAddFlag_triggered();
void on_actionRename_triggered(); void on_actionRename_triggered();
void on_actionRenameUsedHere_triggered(); void on_actionRenameUsedHere_triggered();
@ -53,11 +54,16 @@ private:
RVA offset; RVA offset;
bool canCopy; bool canCopy;
QList<QAction*> anonymousActions;
QAction actionCopy; QAction actionCopy;
QAction *copySeparator; QAction *copySeparator;
QAction actionAddComment; QAction actionAddComment;
QAction actionAddFlag; QAction actionAddFlag;
QAction actionCreateFunction;
QAction actionRename; QAction actionRename;
QAction actionRenameUsedHere; QAction actionRenameUsedHere;
QAction actionXRefs; QAction actionXRefs;
@ -73,5 +79,9 @@ private:
QAction actionSetBaseIPAddr; QAction actionSetBaseIPAddr;
QAction actionSetBaseSyscall; QAction actionSetBaseSyscall;
QAction actionSetBaseString; 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 #endif // DISASSEMBLYCONTEXTMENU_H