mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-19 19:36:11 +00:00
Action to rename functions in the decompiler context menu (#2286)
This commit is contained in:
parent
88f837465f
commit
eef9baa300
@ -658,10 +658,10 @@ bool CutterCore::mapFile(QString path, RVA mapaddr)
|
||||
return true;
|
||||
}
|
||||
|
||||
void CutterCore::renameFunction(const QString &oldName, const QString &newName)
|
||||
void CutterCore::renameFunction(const RVA offset, const QString &newName)
|
||||
{
|
||||
cmdRaw("afn " + newName + " " + oldName);
|
||||
emit functionRenamed(oldName, newName);
|
||||
cmdRaw("afn " + newName + " " + RAddressString(offset));
|
||||
emit functionRenamed(offset, newName);
|
||||
}
|
||||
|
||||
void CutterCore::delFunction(RVA addr)
|
||||
@ -3640,9 +3640,9 @@ void CutterCore::triggerVarsChanged()
|
||||
emit varsChanged();
|
||||
}
|
||||
|
||||
void CutterCore::triggerFunctionRenamed(const QString &prevName, const QString &newName)
|
||||
void CutterCore::triggerFunctionRenamed(const RVA offset, const QString &newName)
|
||||
{
|
||||
emit functionRenamed(prevName, newName);
|
||||
emit functionRenamed(offset, newName);
|
||||
}
|
||||
|
||||
void CutterCore::loadPDB(const QString &file)
|
||||
|
@ -143,7 +143,7 @@ public:
|
||||
QStringList autocomplete(const QString &cmd, RLinePromptType promptType, size_t limit = 4096);
|
||||
|
||||
/* Functions methods */
|
||||
void renameFunction(const QString &oldName, const QString &newName);
|
||||
void renameFunction(const RVA offset, const QString &newName);
|
||||
void delFunction(RVA addr);
|
||||
void renameFlag(QString old_name, QString new_name);
|
||||
|
||||
@ -587,7 +587,7 @@ public:
|
||||
|
||||
/* Signals related */
|
||||
void triggerVarsChanged();
|
||||
void triggerFunctionRenamed(const QString &prevName, const QString &newName);
|
||||
void triggerFunctionRenamed(const RVA offset, const QString &newName);
|
||||
void triggerRefreshAll();
|
||||
void triggerAsmOptionsChanged();
|
||||
void triggerGraphOptionsChanged();
|
||||
@ -636,7 +636,7 @@ public:
|
||||
signals:
|
||||
void refreshAll();
|
||||
|
||||
void functionRenamed(const QString &prev_name, const QString &new_name);
|
||||
void functionRenamed(const RVA offset, const QString &new_name);
|
||||
void varsChanged();
|
||||
void functionsChanged();
|
||||
void flagsChanged();
|
||||
|
@ -10,15 +10,18 @@
|
||||
#include <QClipboard>
|
||||
#include <QApplication>
|
||||
#include <QPushButton>
|
||||
#include <QInputDialog>
|
||||
|
||||
DecompilerContextMenu::DecompilerContextMenu(QWidget *parent, MainWindow *mainWindow)
|
||||
: QMenu(parent),
|
||||
offset(0),
|
||||
isTogglingBreakpoints(false),
|
||||
mainWindow(mainWindow),
|
||||
annotationHere(nullptr),
|
||||
actionCopy(tr("Copy"), this),
|
||||
actionAddComment(tr("Add Comment"), this),
|
||||
actionDeleteComment(tr("Delete comment"), this),
|
||||
actionRenameThingHere(tr("Rename function at cursor"), this),
|
||||
actionToggleBreakpoint(tr("Add/remove breakpoint"), this),
|
||||
actionAdvancedBreakpoint(tr("Advanced breakpoint"), this),
|
||||
breakpointsInLineMenu(new QMenu(this)),
|
||||
@ -31,6 +34,8 @@ DecompilerContextMenu::DecompilerContextMenu(QWidget *parent, MainWindow *mainWi
|
||||
setActionAddComment();
|
||||
setActionDeleteComment();
|
||||
|
||||
setActionRenameThingHere();
|
||||
|
||||
addSeparator();
|
||||
addBreakpointMenu();
|
||||
addDebugMenu();
|
||||
@ -47,6 +52,11 @@ DecompilerContextMenu::~DecompilerContextMenu()
|
||||
{
|
||||
}
|
||||
|
||||
void DecompilerContextMenu::setAnnotationHere(RCodeAnnotation *annotation)
|
||||
{
|
||||
this->annotationHere = annotation;
|
||||
}
|
||||
|
||||
void DecompilerContextMenu::setOffset(RVA offset)
|
||||
{
|
||||
this->offset = offset;
|
||||
@ -152,6 +162,14 @@ void DecompilerContextMenu::aboutToShowSlot()
|
||||
|
||||
QString progCounterName = Core()->getRegisterName("PC").toUpper();
|
||||
actionSetPC.setText(tr("Set %1 here").arg(progCounterName));
|
||||
|
||||
if (!annotationHere) { // To be considered as invalid
|
||||
actionRenameThingHere.setVisible(false);
|
||||
} else {
|
||||
actionRenameThingHere.setVisible(true);
|
||||
actionRenameThingHere.setText(tr("Rename function %1").arg(QString(
|
||||
annotationHere->function_name.name)));
|
||||
}
|
||||
}
|
||||
|
||||
// Set up actions
|
||||
@ -178,6 +196,14 @@ void DecompilerContextMenu::setActionDeleteComment()
|
||||
addAction(&actionDeleteComment);
|
||||
}
|
||||
|
||||
void DecompilerContextMenu::setActionRenameThingHere()
|
||||
{
|
||||
actionRenameThingHere.setShortcut({Qt::SHIFT + Qt::Key_N});
|
||||
connect(&actionRenameThingHere, &QAction::triggered, this,
|
||||
&DecompilerContextMenu::actionRenameThingHereTriggered);
|
||||
addAction(&actionRenameThingHere);
|
||||
}
|
||||
|
||||
void DecompilerContextMenu::setActionToggleBreakpoint()
|
||||
{
|
||||
connect(&actionToggleBreakpoint, &QAction::triggered, this,
|
||||
@ -220,6 +246,34 @@ void DecompilerContextMenu::actionDeleteCommentTriggered()
|
||||
Core()->delComment(this->firstOffsetInLine);
|
||||
}
|
||||
|
||||
void DecompilerContextMenu::actionRenameThingHereTriggered()
|
||||
{
|
||||
if (!annotationHere) {
|
||||
return;
|
||||
}
|
||||
bool ok;
|
||||
auto type = annotationHere->type;
|
||||
if (type == R_CODE_ANNOTATION_TYPE_FUNCTION_NAME) {
|
||||
QString currentName(annotationHere->function_name.name);
|
||||
RVA func_addr = annotationHere->function_name.offset;
|
||||
RAnalFunction *func = Core()->functionAt(func_addr);
|
||||
if (func == NULL) {
|
||||
QString function_name = QInputDialog::getText(this, tr("Define this function at %2").arg(RAddressString(func_addr)),
|
||||
tr("Function name:"), QLineEdit::Normal, currentName, &ok);
|
||||
if (ok && !function_name.isEmpty()) {
|
||||
Core()->createFunctionAt(func_addr, function_name);
|
||||
}
|
||||
} else {
|
||||
QString newName = QInputDialog::getText(this, tr("Rename function %2").arg(currentName),
|
||||
tr("Function name:"), QLineEdit::Normal, currentName, &ok);
|
||||
if (ok && !newName.isEmpty()) {
|
||||
Core()->renameFunction(func_addr, newName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void DecompilerContextMenu::actionToggleBreakpointTriggered()
|
||||
{
|
||||
if (!this->availableBreakpoints.isEmpty()) {
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <QMenu>
|
||||
#include <QKeySequence>
|
||||
|
||||
#include <r_util/r_annotated_code.h>
|
||||
|
||||
class DecompilerContextMenu : public QMenu
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -14,6 +16,7 @@ public:
|
||||
~DecompilerContextMenu();
|
||||
|
||||
bool getIsTogglingBreakpoints();
|
||||
void setAnnotationHere(RCodeAnnotation *annotation);
|
||||
|
||||
signals:
|
||||
void copy();
|
||||
@ -34,6 +37,8 @@ private slots:
|
||||
void actionAddCommentTriggered();
|
||||
void actionDeleteCommentTriggered();
|
||||
|
||||
void actionRenameThingHereTriggered();
|
||||
|
||||
void actionToggleBreakpointTriggered();
|
||||
void actionAdvancedBreakpointTriggered();
|
||||
|
||||
@ -48,12 +53,16 @@ private:
|
||||
QVector<RVA> availableBreakpoints;
|
||||
MainWindow *mainWindow;
|
||||
|
||||
RCodeAnnotation *annotationHere;
|
||||
|
||||
QAction actionCopy;
|
||||
QAction *copySeparator;
|
||||
|
||||
QAction actionAddComment;
|
||||
QAction actionDeleteComment;
|
||||
|
||||
QAction actionRenameThingHere;
|
||||
|
||||
QMenu *breakpointMenu;
|
||||
QAction actionToggleBreakpoint;
|
||||
QAction actionAdvancedBreakpoint;
|
||||
@ -75,6 +84,8 @@ private:
|
||||
void setActionAddComment();
|
||||
void setActionDeleteComment();
|
||||
|
||||
void setActionRenameThingHere();
|
||||
|
||||
void setActionToggleBreakpoint();
|
||||
void setActionAdvancedBreakpoint();
|
||||
|
||||
|
@ -818,7 +818,7 @@ void DisassemblyContextMenu::on_actionRename_triggered()
|
||||
QString newName = QInputDialog::getText(this, tr("Rename function %2").arg(fcn->name),
|
||||
tr("Function name:"), QLineEdit::Normal, fcn->name, &ok);
|
||||
if (ok && !newName.isEmpty()) {
|
||||
Core()->renameFunction(fcn->name, newName);
|
||||
Core()->renameFunction(fcn->addr, newName);
|
||||
}
|
||||
} else if (f) {
|
||||
// Renaming flag
|
||||
@ -863,13 +863,12 @@ void DisassemblyContextMenu::on_actionRenameUsedHere_triggered()
|
||||
// If user accepted
|
||||
if (ok && !newName.isEmpty()) {
|
||||
Core()->cmdRawAt(QString("an %1").arg(newName), offset);
|
||||
|
||||
if (type == ThingUsedHere::Type::Address || type == ThingUsedHere::Type::Flag) {
|
||||
Core()->triggerFlagsChanged();
|
||||
} else if (type == ThingUsedHere::Type::Var) {
|
||||
Core()->triggerVarsChanged();
|
||||
} else if (type == ThingUsedHere::Type::Function) {
|
||||
Core()->triggerFunctionRenamed(oldName, newName);
|
||||
Core()->triggerFunctionRenamed(thingUsedHere.offset, newName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1041,7 +1040,7 @@ void DisassemblyContextMenu::on_actionEditFunction_triggered()
|
||||
|
||||
if (dialog.exec()) {
|
||||
QString new_name = dialog.getNameText();
|
||||
Core()->renameFunction(fcn->name, new_name);
|
||||
Core()->renameFunction(fcn->addr, new_name);
|
||||
QString new_start_addr = dialog.getStartAddrText();
|
||||
fcn->addr = Core()->math(new_start_addr);
|
||||
QString new_stack_size = dialog.getStackSizeText();
|
||||
|
@ -284,7 +284,8 @@ void DecompilerWidget::decompilationFinished(RAnnotatedCode *codeDecompiled)
|
||||
ui->progressLabel->setVisible(false);
|
||||
ui->decompilerComboBox->setEnabled(decompilerSelectionEnabled);
|
||||
updateRefreshButton();
|
||||
|
||||
|
||||
mCtxMenu->setAnnotationHere(nullptr);
|
||||
this->code.reset(codeDecompiled);
|
||||
QString codeString = QString::fromUtf8(this->code->code);
|
||||
if (codeString.isEmpty()) {
|
||||
@ -305,6 +306,23 @@ void DecompilerWidget::decompilationFinished(RAnnotatedCode *codeDecompiled)
|
||||
}
|
||||
}
|
||||
|
||||
void DecompilerWidget::setAnnotationsAtCursor(size_t pos)
|
||||
{
|
||||
RCodeAnnotation *annotationAtPos = nullptr;
|
||||
void *annotationi;
|
||||
r_vector_foreach(&this->code->annotations, annotationi) {
|
||||
RCodeAnnotation *annotation = (RCodeAnnotation *)annotationi;
|
||||
if (annotation->type == R_CODE_ANNOTATION_TYPE_OFFSET ||
|
||||
annotation->type == R_CODE_ANNOTATION_TYPE_SYNTAX_HIGHLIGHT ||
|
||||
annotation->start > pos || annotation->end <= pos) {
|
||||
continue;
|
||||
}
|
||||
annotationAtPos = annotation;
|
||||
break;
|
||||
}
|
||||
mCtxMenu->setAnnotationHere(annotationAtPos);
|
||||
}
|
||||
|
||||
void DecompilerWidget::decompilerSelected()
|
||||
{
|
||||
Config()->setSelectedDecompiler(ui->decompilerComboBox->currentData().toString());
|
||||
@ -333,7 +351,7 @@ void DecompilerWidget::cursorPositionChanged()
|
||||
}
|
||||
|
||||
size_t pos = ui->textEdit->textCursor().position();
|
||||
|
||||
setAnnotationsAtCursor(pos);
|
||||
|
||||
setInfoForBreakpoints();
|
||||
|
||||
|
@ -113,6 +113,8 @@ private:
|
||||
void gatherBreakpointInfo(RAnnotatedCode &codeDecompiled, size_t startPos, size_t endPos);
|
||||
|
||||
void setInfoForBreakpoints();
|
||||
|
||||
void setAnnotationsAtCursor(size_t pos);
|
||||
};
|
||||
|
||||
#endif // DECOMPILERWIDGET_H
|
||||
|
@ -43,8 +43,7 @@ DisassemblerGraphView::DisassemblerGraphView(QWidget *parent, CutterSeekable *se
|
||||
// Signals that require a refresh all
|
||||
connect(Core(), SIGNAL(refreshAll()), this, SLOT(refreshView()));
|
||||
connect(Core(), SIGNAL(commentsChanged()), this, SLOT(refreshView()));
|
||||
connect(Core(), SIGNAL(functionRenamed(const QString &, const QString &)), this,
|
||||
SLOT(refreshView()));
|
||||
connect(Core(), &CutterCore::functionRenamed, this, &DisassemblerGraphView::refreshView);
|
||||
connect(Core(), SIGNAL(flagsChanged()), this, SLOT(refreshView()));
|
||||
connect(Core(), SIGNAL(varsChanged()), this, SLOT(refreshView()));
|
||||
connect(Core(), SIGNAL(instructionChanged(RVA)), this, SLOT(refreshView()));
|
||||
|
@ -148,8 +148,7 @@ DisassemblyWidget::DisassemblyWidget(MainWindow *main)
|
||||
connect(Core(), SIGNAL(commentsChanged()), this, SLOT(refreshDisasm()));
|
||||
connect(Core(), SIGNAL(flagsChanged()), this, SLOT(refreshDisasm()));
|
||||
connect(Core(), SIGNAL(functionsChanged()), this, SLOT(refreshDisasm()));
|
||||
connect(Core(), SIGNAL(functionRenamed(const QString &, const QString &)), this,
|
||||
SLOT(refreshDisasm()));
|
||||
connect(Core(), &CutterCore::functionRenamed, this, [this]() {refreshDisasm();});
|
||||
connect(Core(), SIGNAL(varsChanged()), this, SLOT(refreshDisasm()));
|
||||
connect(Core(), SIGNAL(asmOptionsChanged()), this, SLOT(refreshDisasm()));
|
||||
connect(Core(), &CutterCore::instructionChanged, this, [this](RVA offset) {
|
||||
|
@ -334,11 +334,11 @@ bool FunctionModel::updateCurrentIndex()
|
||||
return changed;
|
||||
}
|
||||
|
||||
void FunctionModel::functionRenamed(const QString &prev_name, const QString &new_name)
|
||||
void FunctionModel::functionRenamed(const RVA offset, const QString &new_name)
|
||||
{
|
||||
for (int i = 0; i < functions->count(); i++) {
|
||||
FunctionDescription &function = (*functions)[i];
|
||||
if (function.name == prev_name) {
|
||||
if (function.offset == offset) {
|
||||
function.name = new_name;
|
||||
emit dataChanged(index(i, 0), index(i, columnCount() - 1));
|
||||
}
|
||||
@ -533,7 +533,7 @@ void FunctionsWidget::onActionFunctionsRenameTriggered()
|
||||
// If user accepted
|
||||
if (ok && !newName.isEmpty()) {
|
||||
// Rename function in r2 core
|
||||
Core()->renameFunction(function.name, newName);
|
||||
Core()->renameFunction(function.offset, newName);
|
||||
|
||||
// Seek to new renamed function
|
||||
Core()->seekAndShow(function.offset);
|
||||
|
@ -69,7 +69,7 @@ public:
|
||||
QString name(const QModelIndex &index) const override;
|
||||
private slots:
|
||||
void seekChanged(RVA addr);
|
||||
void functionRenamed(const QString &prev_name, const QString &new_name);
|
||||
void functionRenamed(const RVA offset, const QString &new_name);
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user