mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-31 00:35:05 +00:00
Add context menu entries for target address (#1712)
* Refactor "used here" logic. * Add menu for showing instruction target.
This commit is contained in:
parent
468100c52d
commit
f50fecc57b
@ -915,7 +915,7 @@ QMenu *MainWindow::createShowInMenu(QWidget *parent, RVA address)
|
||||
auto createAddNewWidgetAction = [this, menu, address](QString label, MemoryWidgetType type) {
|
||||
QAction *action = new QAction(label, menu);
|
||||
connect(action, &QAction::triggered, this, [this, address, type](){
|
||||
addNewMemoryWidget(type, address, true);
|
||||
addNewMemoryWidget(type, address, false);
|
||||
});
|
||||
menu->addAction(action);
|
||||
};
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <QApplication>
|
||||
#include <QPushButton>
|
||||
|
||||
DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow* mainWindow)
|
||||
DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow *mainWindow)
|
||||
: QMenu(parent),
|
||||
offset(0),
|
||||
canCopy(false),
|
||||
@ -27,7 +27,8 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow* main
|
||||
initAction(&actionCopy, tr("Copy"), SLOT(on_actionCopy_triggered()), getCopySequence());
|
||||
addAction(&actionCopy);
|
||||
|
||||
initAction(&actionCopyAddr, tr("Copy address"), SLOT(on_actionCopyAddr_triggered()), getCopyAddressSequence());
|
||||
initAction(&actionCopyAddr, tr("Copy address"), SLOT(on_actionCopyAddr_triggered()),
|
||||
getCopyAddressSequence());
|
||||
addAction(&actionCopyAddr);
|
||||
|
||||
initAction(&showInSubmenu, tr("Show in"), nullptr);
|
||||
@ -112,9 +113,6 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow* main
|
||||
|
||||
DisassemblyContextMenu::~DisassemblyContextMenu()
|
||||
{
|
||||
for (QAction *action : anonymousActions) {
|
||||
delete action;
|
||||
}
|
||||
}
|
||||
|
||||
void DisassemblyContextMenu::addSetBaseMenu()
|
||||
@ -249,6 +247,65 @@ void DisassemblyContextMenu::addDebugMenu()
|
||||
debugMenu->addAction(&actionSetPC);
|
||||
}
|
||||
|
||||
QVector<DisassemblyContextMenu::ThingUsedHere> DisassemblyContextMenu::getThingUsedHere(RVA offset)
|
||||
{
|
||||
QVector<ThingUsedHere> result;
|
||||
const QJsonArray array = Core()->cmdj("anj @ " + QString::number(offset)).array();
|
||||
result.reserve(array.size());
|
||||
for (const auto &thing : array) {
|
||||
auto obj = thing.toObject();
|
||||
RVA offset = obj["offset"].toVariant().toULongLong();
|
||||
QString name = obj["name"].toString();
|
||||
QString typeString = obj["type"].toString();
|
||||
ThingUsedHere::Type type = ThingUsedHere::Type::Address;
|
||||
if (typeString == "var") {
|
||||
type = ThingUsedHere::Type::Var;
|
||||
} else if (typeString == "flag") {
|
||||
type = ThingUsedHere::Type::Flag;
|
||||
} else if (typeString == "function") {
|
||||
type = ThingUsedHere::Type::Function;
|
||||
} else if (typeString == "address") {
|
||||
type = ThingUsedHere::Type::Address;
|
||||
}
|
||||
result.push_back(ThingUsedHere{name, offset, type});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void DisassemblyContextMenu::updateTargetMenuActions(const QVector<ThingUsedHere> &targets)
|
||||
{
|
||||
for (auto action : showTargetMenuActions) {
|
||||
removeAction(action);
|
||||
auto menu = action->menu();
|
||||
if (menu) {
|
||||
menu->deleteLater();
|
||||
}
|
||||
action->deleteLater();
|
||||
}
|
||||
showTargetMenuActions.clear();
|
||||
for (auto &target : targets) {
|
||||
QString name;
|
||||
if (target.name.isEmpty()) {
|
||||
name = tr("%1 (used here)").arg(RAddressString(target.offset));
|
||||
} else {
|
||||
name = tr("%1 (%2)").arg(target.name, RAddressString(target.offset));
|
||||
}
|
||||
auto action = new QAction(name, this);
|
||||
showTargetMenuActions.append(action);
|
||||
auto menu = mainWindow->createShowInMenu(this, target.offset);
|
||||
action->setMenu(menu);
|
||||
QAction *copyAddress = new QAction(tr("Copy address"), menu);
|
||||
RVA offset = target.offset;
|
||||
connect(copyAddress, &QAction::triggered, copyAddress, [offset]() {
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
clipboard->setText(RAddressString(offset));
|
||||
});
|
||||
menu->addSeparator();
|
||||
menu->addAction(copyAddress);
|
||||
}
|
||||
insertActions(copySeparator, showTargetMenuActions);
|
||||
}
|
||||
|
||||
void DisassemblyContextMenu::setOffset(RVA offset)
|
||||
{
|
||||
this->offset = offset;
|
||||
@ -362,24 +419,22 @@ void DisassemblyContextMenu::aboutToShowSlot()
|
||||
|
||||
|
||||
// Only show "rename X used here" if there is something to rename
|
||||
QJsonArray thingUsedHereArray = Core()->cmdj("anj @ " + QString::number(offset)).array();
|
||||
if (!thingUsedHereArray.isEmpty()) {
|
||||
auto thingsUsedHere = getThingUsedHere(offset);
|
||||
if (!thingsUsedHere.isEmpty()) {
|
||||
actionRenameUsedHere.setVisible(true);
|
||||
QJsonObject thingUsedHere = thingUsedHereArray.first().toObject();
|
||||
if (thingUsedHere["type"] == "address") {
|
||||
RVA offset = thingUsedHere["offset"].toVariant().toULongLong();
|
||||
auto &thingUsedHere = thingsUsedHere.first();
|
||||
if (thingUsedHere.type == ThingUsedHere::Type::Address) {
|
||||
RVA offset = thingUsedHere.offset;
|
||||
actionRenameUsedHere.setText(tr("Add flag at %1 (used here)").arg(RAddressString(offset)));
|
||||
} else {
|
||||
if (thingUsedHere["type"] == "function") {
|
||||
actionRenameUsedHere.setText(tr("Rename \"%1\"").arg(thingUsedHere["name"].toString()));
|
||||
}
|
||||
else {
|
||||
actionRenameUsedHere.setText(tr("Rename \"%1\" (used here)").arg(thingUsedHere["name"].toString()));
|
||||
}
|
||||
} else if (thingUsedHere.type == ThingUsedHere::Type::Function) {
|
||||
actionRenameUsedHere.setText(tr("Rename \"%1\"").arg(thingUsedHere.name));
|
||||
} else {
|
||||
actionRenameUsedHere.setText(tr("Rename \"%1\" (used here)").arg(thingUsedHere.name));
|
||||
}
|
||||
} else {
|
||||
actionRenameUsedHere.setVisible(false);
|
||||
}
|
||||
updateTargetMenuActions(thingsUsedHere);
|
||||
|
||||
// Decide to show Reverse jmp option
|
||||
showReverseJmpQuery();
|
||||
@ -686,38 +741,39 @@ void DisassemblyContextMenu::on_actionRename_triggered()
|
||||
|
||||
void DisassemblyContextMenu::on_actionRenameUsedHere_triggered()
|
||||
{
|
||||
QJsonArray array = Core()->cmdj("anj @ " + QString::number(offset)).array();
|
||||
auto array = getThingUsedHere(offset);
|
||||
if (array.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonObject thingUsedHere = array.first().toObject();
|
||||
QString type = thingUsedHere.value("type").toString();
|
||||
auto thingUsedHere = array.first();
|
||||
|
||||
RenameDialog dialog(this);
|
||||
|
||||
QString oldName;
|
||||
auto type = thingUsedHere.type;
|
||||
|
||||
if (type == "address") {
|
||||
RVA offset = thingUsedHere["offset"].toVariant().toULongLong();
|
||||
if (type == ThingUsedHere::Type::Address) {
|
||||
RVA offset = thingUsedHere.offset;
|
||||
dialog.setWindowTitle(tr("Add flag at %1").arg(RAddressString(offset)));
|
||||
dialog.setName("label." + QString::number(offset, 16));
|
||||
} else {
|
||||
oldName = thingUsedHere.value("name").toString();
|
||||
oldName = thingUsedHere.name;
|
||||
dialog.setWindowTitle(tr("Rename %1").arg(oldName));
|
||||
dialog.setName(oldName);
|
||||
}
|
||||
|
||||
|
||||
if (dialog.exec()) {
|
||||
QString newName = dialog.getName().trimmed();
|
||||
if (!newName.isEmpty()) {
|
||||
Core()->cmd("an " + newName + " @ " + QString::number(offset));
|
||||
|
||||
if (type == "address" || type == "flag") {
|
||||
if (type == ThingUsedHere::Type::Address || type == ThingUsedHere::Type::Address) {
|
||||
Core()->triggerFlagsChanged();
|
||||
} else if (type == "var") {
|
||||
} else if (type == ThingUsedHere::Type::Var) {
|
||||
Core()->triggerVarsChanged();
|
||||
} else if (type == "function") {
|
||||
} else if (type == ThingUsedHere::Type::Function) {
|
||||
Core()->triggerFunctionRenamed(oldName, newName);
|
||||
}
|
||||
}
|
||||
@ -729,7 +785,8 @@ void DisassemblyContextMenu::on_actionSetFunctionVarTypes_triggered()
|
||||
RAnalFunction *fcn = Core()->functionAt(offset);
|
||||
|
||||
if (!fcn) {
|
||||
QMessageBox::critical(this, tr("Re-type function local vars"), tr("You must be in a function to define variable types."));
|
||||
QMessageBox::critical(this, tr("Re-type function local vars"),
|
||||
tr("You must be in a function to define variable types."));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -873,7 +930,7 @@ void DisassemblyContextMenu::setToData(int size, int repeat)
|
||||
QAction *DisassemblyContextMenu::addAnonymousAction(QString name, const char *slot,
|
||||
QKeySequence keySequence)
|
||||
{
|
||||
auto action = new QAction();
|
||||
auto action = new QAction(this);
|
||||
addAction(action);
|
||||
anonymousActions.append(action);
|
||||
initAction(action, name, slot, keySequence);
|
||||
|
@ -10,7 +10,7 @@ class DisassemblyContextMenu : public QMenu
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DisassemblyContextMenu(QWidget *parent, MainWindow* mainWindow);
|
||||
DisassemblyContextMenu(QWidget *parent, MainWindow *mainWindow);
|
||||
~DisassemblyContextMenu();
|
||||
|
||||
signals:
|
||||
@ -101,7 +101,7 @@ private:
|
||||
RVA offset;
|
||||
bool canCopy;
|
||||
QString curHighlightedWord; // The current highlighted word
|
||||
MainWindow* mainWindow;
|
||||
MainWindow *mainWindow;
|
||||
|
||||
QList<QAction *> anonymousActions;
|
||||
|
||||
@ -166,6 +166,7 @@ private:
|
||||
QAction actionSetToDataQword;
|
||||
|
||||
QAction showInSubmenu;
|
||||
QList<QAction*> showTargetMenuActions;
|
||||
|
||||
// For creating anonymous entries (that are always visible)
|
||||
QAction *addAnonymousAction(QString name, const char *slot, QKeySequence shortcut);
|
||||
@ -184,5 +185,20 @@ private:
|
||||
void addSetToDataMenu();
|
||||
void addEditMenu();
|
||||
void addDebugMenu();
|
||||
|
||||
struct ThingUsedHere {
|
||||
QString name;
|
||||
RVA offset;
|
||||
enum class Type {
|
||||
Var,
|
||||
Function,
|
||||
Flag,
|
||||
Address
|
||||
};
|
||||
Type type;
|
||||
};
|
||||
QVector<ThingUsedHere> getThingUsedHere(RVA offset);
|
||||
|
||||
void updateTargetMenuActions(const QVector<ThingUsedHere> &targets);
|
||||
};
|
||||
#endif // DISASSEMBLYCONTEXTMENU_H
|
||||
|
Loading…
Reference in New Issue
Block a user