Skip to content

Commit

Permalink
Action to rename functions in the decompiler context menu (#2286)
Browse files Browse the repository at this point in the history
  • Loading branch information
NirmalManoj committed Aug 6, 2020
1 parent 9ba0226 commit 8db135e
Show file tree
Hide file tree
Showing 13 changed files with 106 additions and 24 deletions.
2 changes: 1 addition & 1 deletion .appveyor.yml
Expand Up @@ -33,7 +33,7 @@ environment:
DEPLOY: false

install:
- cmd: if defined QMAKE ( git clone --depth 1 --recurse-submodules https://github.com/radareorg/r2ghidra-dec.git %APPVEYOR_BUILD_FOLDER%/r2ghidra-dec )
- cmd: if defined QMAKE ( git clone --depth 1 --branch decompiler-refactoring --recurse-submodules https://github.com/radareorg/r2ghidra-dec.git %APPVEYOR_BUILD_FOLDER%/r2ghidra-dec )
- ps: $env:path = ($env:path -split ";").Where({!($_ -like "*Microsoft SQL Server*")}) -join ";"
- cmd: C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER && scripts/fetch_deps.sh"
- cmd: set "CUTTER_DEPS_DIR=%APPVEYOR_BUILD_FOLDER%\cutter-deps"
Expand Down
2 changes: 1 addition & 1 deletion scripts/r2ghidra.sh
Expand Up @@ -5,7 +5,7 @@ SCRIPTPATH=$(realpath "$(dirname "${BASH_SOURCE[0]}")")
cd "$SCRIPTPATH/.."

if [[ ! -d r2ghidra-dec ]]; then
git clone --depth 1 --recurse-submodules https://github.com/radareorg/r2ghidra-dec.git || exit 1
git clone --depth 1 --branch decompiler-refactoring --recurse-submodules https://github.com/radareorg/r2ghidra-dec.git || exit 1
fi
cd r2ghidra-dec || exit 1

Expand Down
10 changes: 5 additions & 5 deletions src/core/Cutter.cpp
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions src/core/Cutter.h
Expand Up @@ -144,7 +144,7 @@ class CUTTER_EXPORT CutterCore: public QObject
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);

Expand Down Expand Up @@ -588,7 +588,7 @@ class CUTTER_EXPORT CutterCore: public QObject

/* 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();
Expand Down Expand Up @@ -637,7 +637,7 @@ class CUTTER_EXPORT CutterCore: public QObject
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();
Expand Down
54 changes: 54 additions & 0 deletions src/menus/DecompilerContextMenu.cpp
Expand Up @@ -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)),
Expand All @@ -31,6 +34,8 @@ DecompilerContextMenu::DecompilerContextMenu(QWidget *parent, MainWindow *mainWi
setActionAddComment();
setActionDeleteComment();

setActionRenameThingHere();

addSeparator();
addBreakpointMenu();
addDebugMenu();
Expand All @@ -47,6 +52,11 @@ DecompilerContextMenu::~DecompilerContextMenu()
{
}

void DecompilerContextMenu::setAnnotationHere(RCodeAnnotation *annotation)
{
this->annotationHere = annotation;
}

void DecompilerContextMenu::setOffset(RVA offset)
{
this->offset = offset;
Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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()) {
Expand Down
11 changes: 11 additions & 0 deletions src/menus/DecompilerContextMenu.h
Expand Up @@ -5,6 +5,8 @@
#include <QMenu>
#include <QKeySequence>

#include <r_util/r_annotated_code.h>

class DecompilerContextMenu : public QMenu
{
Q_OBJECT
Expand All @@ -14,6 +16,7 @@ class DecompilerContextMenu : public QMenu
~DecompilerContextMenu();

bool getIsTogglingBreakpoints();
void setAnnotationHere(RCodeAnnotation *annotation);

signals:
void copy();
Expand All @@ -34,6 +37,8 @@ private slots:
void actionAddCommentTriggered();
void actionDeleteCommentTriggered();

void actionRenameThingHereTriggered();

void actionToggleBreakpointTriggered();
void actionAdvancedBreakpointTriggered();

Expand All @@ -48,12 +53,16 @@ private slots:
QVector<RVA> availableBreakpoints;
MainWindow *mainWindow;

RCodeAnnotation *annotationHere;

QAction actionCopy;
QAction *copySeparator;

QAction actionAddComment;
QAction actionDeleteComment;

QAction actionRenameThingHere;

QMenu *breakpointMenu;
QAction actionToggleBreakpoint;
QAction actionAdvancedBreakpoint;
Expand All @@ -75,6 +84,8 @@ private slots:
void setActionAddComment();
void setActionDeleteComment();

void setActionRenameThingHere();

void setActionToggleBreakpoint();
void setActionAdvancedBreakpoint();

Expand Down
7 changes: 3 additions & 4 deletions src/menus/DisassemblyContextMenu.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
}
}
Expand Down Expand Up @@ -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();
Expand Down
22 changes: 20 additions & 2 deletions src/widgets/DecompilerWidget.cpp
Expand Up @@ -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()) {
Expand All @@ -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());
Expand Down Expand Up @@ -333,7 +351,7 @@ void DecompilerWidget::cursorPositionChanged()
}

size_t pos = ui->textEdit->textCursor().position();

setAnnotationsAtCursor(pos);

setInfoForBreakpoints();

Expand Down
2 changes: 2 additions & 0 deletions src/widgets/DecompilerWidget.h
Expand Up @@ -113,6 +113,8 @@ private slots:
void gatherBreakpointInfo(RAnnotatedCode &codeDecompiled, size_t startPos, size_t endPos);

void setInfoForBreakpoints();

void setAnnotationsAtCursor(size_t pos);
};

#endif // DECOMPILERWIDGET_H
3 changes: 1 addition & 2 deletions src/widgets/DisassemblerGraphView.cpp
Expand Up @@ -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()));
Expand Down
3 changes: 1 addition & 2 deletions src/widgets/DisassemblyWidget.cpp
Expand Up @@ -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) {
Expand Down
6 changes: 3 additions & 3 deletions src/widgets/FunctionsWidget.cpp
Expand Up @@ -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));
}
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/widgets/FunctionsWidget.h
Expand Up @@ -69,7 +69,7 @@ class FunctionModel : public AddressableItemModel<>
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);
};


Expand Down

0 comments on commit 8db135e

Please sign in to comment.