Skip to content

Commit f50fecc

Browse files
karlissITAYC0HEN
authored andcommittedAug 14, 2019
Add context menu entries for target address (rizinorg#1712)
* Refactor "used here" logic. * Add menu for showing instruction target.
1 parent 468100c commit f50fecc

File tree

3 files changed

+104
-31
lines changed

3 files changed

+104
-31
lines changed
 

‎src/core/MainWindow.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,7 @@ QMenu *MainWindow::createShowInMenu(QWidget *parent, RVA address)
915915
auto createAddNewWidgetAction = [this, menu, address](QString label, MemoryWidgetType type) {
916916
QAction *action = new QAction(label, menu);
917917
connect(action, &QAction::triggered, this, [this, address, type](){
918-
addNewMemoryWidget(type, address, true);
918+
addNewMemoryWidget(type, address, false);
919919
});
920920
menu->addAction(action);
921921
};

‎src/menus/DisassemblyContextMenu.cpp

+85-28
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#include <QApplication>
1919
#include <QPushButton>
2020

21-
DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow* mainWindow)
21+
DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow *mainWindow)
2222
: QMenu(parent),
2323
offset(0),
2424
canCopy(false),
@@ -27,7 +27,8 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow* main
2727
initAction(&actionCopy, tr("Copy"), SLOT(on_actionCopy_triggered()), getCopySequence());
2828
addAction(&actionCopy);
2929

30-
initAction(&actionCopyAddr, tr("Copy address"), SLOT(on_actionCopyAddr_triggered()), getCopyAddressSequence());
30+
initAction(&actionCopyAddr, tr("Copy address"), SLOT(on_actionCopyAddr_triggered()),
31+
getCopyAddressSequence());
3132
addAction(&actionCopyAddr);
3233

3334
initAction(&showInSubmenu, tr("Show in"), nullptr);
@@ -112,9 +113,6 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow* main
112113

113114
DisassemblyContextMenu::~DisassemblyContextMenu()
114115
{
115-
for (QAction *action : anonymousActions) {
116-
delete action;
117-
}
118116
}
119117

120118
void DisassemblyContextMenu::addSetBaseMenu()
@@ -249,6 +247,65 @@ void DisassemblyContextMenu::addDebugMenu()
249247
debugMenu->addAction(&actionSetPC);
250248
}
251249

250+
QVector<DisassemblyContextMenu::ThingUsedHere> DisassemblyContextMenu::getThingUsedHere(RVA offset)
251+
{
252+
QVector<ThingUsedHere> result;
253+
const QJsonArray array = Core()->cmdj("anj @ " + QString::number(offset)).array();
254+
result.reserve(array.size());
255+
for (const auto &thing : array) {
256+
auto obj = thing.toObject();
257+
RVA offset = obj["offset"].toVariant().toULongLong();
258+
QString name = obj["name"].toString();
259+
QString typeString = obj["type"].toString();
260+
ThingUsedHere::Type type = ThingUsedHere::Type::Address;
261+
if (typeString == "var") {
262+
type = ThingUsedHere::Type::Var;
263+
} else if (typeString == "flag") {
264+
type = ThingUsedHere::Type::Flag;
265+
} else if (typeString == "function") {
266+
type = ThingUsedHere::Type::Function;
267+
} else if (typeString == "address") {
268+
type = ThingUsedHere::Type::Address;
269+
}
270+
result.push_back(ThingUsedHere{name, offset, type});
271+
}
272+
return result;
273+
}
274+
275+
void DisassemblyContextMenu::updateTargetMenuActions(const QVector<ThingUsedHere> &targets)
276+
{
277+
for (auto action : showTargetMenuActions) {
278+
removeAction(action);
279+
auto menu = action->menu();
280+
if (menu) {
281+
menu->deleteLater();
282+
}
283+
action->deleteLater();
284+
}
285+
showTargetMenuActions.clear();
286+
for (auto &target : targets) {
287+
QString name;
288+
if (target.name.isEmpty()) {
289+
name = tr("%1 (used here)").arg(RAddressString(target.offset));
290+
} else {
291+
name = tr("%1 (%2)").arg(target.name, RAddressString(target.offset));
292+
}
293+
auto action = new QAction(name, this);
294+
showTargetMenuActions.append(action);
295+
auto menu = mainWindow->createShowInMenu(this, target.offset);
296+
action->setMenu(menu);
297+
QAction *copyAddress = new QAction(tr("Copy address"), menu);
298+
RVA offset = target.offset;
299+
connect(copyAddress, &QAction::triggered, copyAddress, [offset]() {
300+
QClipboard *clipboard = QApplication::clipboard();
301+
clipboard->setText(RAddressString(offset));
302+
});
303+
menu->addSeparator();
304+
menu->addAction(copyAddress);
305+
}
306+
insertActions(copySeparator, showTargetMenuActions);
307+
}
308+
252309
void DisassemblyContextMenu::setOffset(RVA offset)
253310
{
254311
this->offset = offset;
@@ -362,24 +419,22 @@ void DisassemblyContextMenu::aboutToShowSlot()
362419

363420

364421
// Only show "rename X used here" if there is something to rename
365-
QJsonArray thingUsedHereArray = Core()->cmdj("anj @ " + QString::number(offset)).array();
366-
if (!thingUsedHereArray.isEmpty()) {
422+
auto thingsUsedHere = getThingUsedHere(offset);
423+
if (!thingsUsedHere.isEmpty()) {
367424
actionRenameUsedHere.setVisible(true);
368-
QJsonObject thingUsedHere = thingUsedHereArray.first().toObject();
369-
if (thingUsedHere["type"] == "address") {
370-
RVA offset = thingUsedHere["offset"].toVariant().toULongLong();
425+
auto &thingUsedHere = thingsUsedHere.first();
426+
if (thingUsedHere.type == ThingUsedHere::Type::Address) {
427+
RVA offset = thingUsedHere.offset;
371428
actionRenameUsedHere.setText(tr("Add flag at %1 (used here)").arg(RAddressString(offset)));
372-
} else {
373-
if (thingUsedHere["type"] == "function") {
374-
actionRenameUsedHere.setText(tr("Rename \"%1\"").arg(thingUsedHere["name"].toString()));
375-
}
376-
else {
377-
actionRenameUsedHere.setText(tr("Rename \"%1\" (used here)").arg(thingUsedHere["name"].toString()));
378-
}
429+
} else if (thingUsedHere.type == ThingUsedHere::Type::Function) {
430+
actionRenameUsedHere.setText(tr("Rename \"%1\"").arg(thingUsedHere.name));
431+
} else {
432+
actionRenameUsedHere.setText(tr("Rename \"%1\" (used here)").arg(thingUsedHere.name));
379433
}
380434
} else {
381435
actionRenameUsedHere.setVisible(false);
382436
}
437+
updateTargetMenuActions(thingsUsedHere);
383438

384439
// Decide to show Reverse jmp option
385440
showReverseJmpQuery();
@@ -686,38 +741,39 @@ void DisassemblyContextMenu::on_actionRename_triggered()
686741

687742
void DisassemblyContextMenu::on_actionRenameUsedHere_triggered()
688743
{
689-
QJsonArray array = Core()->cmdj("anj @ " + QString::number(offset)).array();
744+
auto array = getThingUsedHere(offset);
690745
if (array.isEmpty()) {
691746
return;
692747
}
693748

694-
QJsonObject thingUsedHere = array.first().toObject();
695-
QString type = thingUsedHere.value("type").toString();
749+
auto thingUsedHere = array.first();
696750

697751
RenameDialog dialog(this);
698752

699753
QString oldName;
754+
auto type = thingUsedHere.type;
700755

701-
if (type == "address") {
702-
RVA offset = thingUsedHere["offset"].toVariant().toULongLong();
756+
if (type == ThingUsedHere::Type::Address) {
757+
RVA offset = thingUsedHere.offset;
703758
dialog.setWindowTitle(tr("Add flag at %1").arg(RAddressString(offset)));
704759
dialog.setName("label." + QString::number(offset, 16));
705760
} else {
706-
oldName = thingUsedHere.value("name").toString();
761+
oldName = thingUsedHere.name;
707762
dialog.setWindowTitle(tr("Rename %1").arg(oldName));
708763
dialog.setName(oldName);
709764
}
710765

766+
711767
if (dialog.exec()) {
712768
QString newName = dialog.getName().trimmed();
713769
if (!newName.isEmpty()) {
714770
Core()->cmd("an " + newName + " @ " + QString::number(offset));
715771

716-
if (type == "address" || type == "flag") {
772+
if (type == ThingUsedHere::Type::Address || type == ThingUsedHere::Type::Address) {
717773
Core()->triggerFlagsChanged();
718-
} else if (type == "var") {
774+
} else if (type == ThingUsedHere::Type::Var) {
719775
Core()->triggerVarsChanged();
720-
} else if (type == "function") {
776+
} else if (type == ThingUsedHere::Type::Function) {
721777
Core()->triggerFunctionRenamed(oldName, newName);
722778
}
723779
}
@@ -729,7 +785,8 @@ void DisassemblyContextMenu::on_actionSetFunctionVarTypes_triggered()
729785
RAnalFunction *fcn = Core()->functionAt(offset);
730786

731787
if (!fcn) {
732-
QMessageBox::critical(this, tr("Re-type function local vars"), tr("You must be in a function to define variable types."));
788+
QMessageBox::critical(this, tr("Re-type function local vars"),
789+
tr("You must be in a function to define variable types."));
733790
return;
734791
}
735792

@@ -873,7 +930,7 @@ void DisassemblyContextMenu::setToData(int size, int repeat)
873930
QAction *DisassemblyContextMenu::addAnonymousAction(QString name, const char *slot,
874931
QKeySequence keySequence)
875932
{
876-
auto action = new QAction();
933+
auto action = new QAction(this);
877934
addAction(action);
878935
anonymousActions.append(action);
879936
initAction(action, name, slot, keySequence);

‎src/menus/DisassemblyContextMenu.h

+18-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class DisassemblyContextMenu : public QMenu
1010
Q_OBJECT
1111

1212
public:
13-
DisassemblyContextMenu(QWidget *parent, MainWindow* mainWindow);
13+
DisassemblyContextMenu(QWidget *parent, MainWindow *mainWindow);
1414
~DisassemblyContextMenu();
1515

1616
signals:
@@ -101,7 +101,7 @@ private slots:
101101
RVA offset;
102102
bool canCopy;
103103
QString curHighlightedWord; // The current highlighted word
104-
MainWindow* mainWindow;
104+
MainWindow *mainWindow;
105105

106106
QList<QAction *> anonymousActions;
107107

@@ -166,6 +166,7 @@ private slots:
166166
QAction actionSetToDataQword;
167167

168168
QAction showInSubmenu;
169+
QList<QAction*> showTargetMenuActions;
169170

170171
// For creating anonymous entries (that are always visible)
171172
QAction *addAnonymousAction(QString name, const char *slot, QKeySequence shortcut);
@@ -184,5 +185,20 @@ private slots:
184185
void addSetToDataMenu();
185186
void addEditMenu();
186187
void addDebugMenu();
188+
189+
struct ThingUsedHere {
190+
QString name;
191+
RVA offset;
192+
enum class Type {
193+
Var,
194+
Function,
195+
Flag,
196+
Address
197+
};
198+
Type type;
199+
};
200+
QVector<ThingUsedHere> getThingUsedHere(RVA offset);
201+
202+
void updateTargetMenuActions(const QVector<ThingUsedHere> &targets);
187203
};
188204
#endif // DISASSEMBLYCONTEXTMENU_H

0 commit comments

Comments
 (0)
Please sign in to comment.