mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-03 18:31:08 +00:00
Reworked renaming in disassembly widgets (#2468)
This commit is contained in:
parent
b07bffc5fe
commit
b02100b66b
@ -47,7 +47,7 @@ Add Flag
|
||||
|
||||
Rename
|
||||
----------------------------------------
|
||||
**Description:** Rename the flag in the current location.
|
||||
**Description:** Rename the flag, function or local variable at current location. If empty, remove the currently associated name.
|
||||
|
||||
**Steps:** Right-click an address or item and choose ``Rename``
|
||||
|
||||
@ -61,14 +61,6 @@ Edit Function
|
||||
|
||||
**Shortcut:** :kbd:`Shift` + :kbd:`P`
|
||||
|
||||
Rename Flag/Function/Variable
|
||||
----------------------------------------
|
||||
**Description:** Rename a specific flag, variable or function under the cursor.
|
||||
|
||||
**Steps:** -> Rename Flag/Fcn/Var Used Here
|
||||
|
||||
**Shortcut:** :kbd:`Shift` + :kbd:`N`
|
||||
|
||||
Re-type Local Variables
|
||||
----------------------------------------
|
||||
**Description:** Rename or set the types of the function's variables and arguments.
|
||||
|
@ -8,26 +8,65 @@
|
||||
FlagDialog::FlagDialog(RVA offset, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::FlagDialog),
|
||||
offset(offset)
|
||||
offset(offset),
|
||||
flagName(""),
|
||||
flagOffset(RVA_INVALID)
|
||||
{
|
||||
// Setup UI
|
||||
ui->setupUi(this);
|
||||
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||
RFlagItem* flag = r_flag_get_i(Core()->core()->flags, offset);
|
||||
if (flag) {
|
||||
flagName = QString(flag->name);
|
||||
flagOffset = flag->offset;
|
||||
}
|
||||
|
||||
auto size_validator = new QIntValidator(ui->sizeEdit);
|
||||
size_validator->setBottom(1);
|
||||
ui->sizeEdit->setValidator(size_validator);
|
||||
if (flag) {
|
||||
ui->nameEdit->setText(flag->name);
|
||||
ui->labelAction->setText(tr("Edit flag at %1").arg(RAddressString(offset)));
|
||||
} else {
|
||||
ui->labelAction->setText(tr("Add flag at %1").arg(RAddressString(offset)));
|
||||
}
|
||||
|
||||
// Connect slots
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted,
|
||||
this, &FlagDialog::buttonBoxAccepted);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected,
|
||||
this, &FlagDialog::buttonBoxRejected);
|
||||
}
|
||||
|
||||
FlagDialog::~FlagDialog() {}
|
||||
FlagDialog::~FlagDialog() { }
|
||||
|
||||
void FlagDialog::on_buttonBox_accepted()
|
||||
void FlagDialog::buttonBoxAccepted()
|
||||
{
|
||||
QString name = ui->nameEdit->text();
|
||||
RVA size = ui->sizeEdit->text().toULongLong();
|
||||
Core()->addFlag(offset, name, size);
|
||||
QString name = ui->nameEdit->text();
|
||||
|
||||
if (name.isEmpty()) {
|
||||
if (flagOffset != RVA_INVALID) {
|
||||
// Empty name and flag exists -> delete the flag
|
||||
Core()->delFlag(flagOffset);
|
||||
} else {
|
||||
// Flag was not existing and we gave an empty name, do nothing
|
||||
}
|
||||
} else {
|
||||
if (flagOffset != RVA_INVALID) {
|
||||
// Name provided and flag exists -> rename the flag
|
||||
Core()->renameFlag(flagName, name);
|
||||
} else {
|
||||
// Name provided and flag does not exist -> create the flag
|
||||
Core()->addFlag(offset, name, size);
|
||||
}
|
||||
}
|
||||
close();
|
||||
this->setResult(QDialog::Accepted);
|
||||
}
|
||||
|
||||
void FlagDialog::on_buttonBox_rejected()
|
||||
void FlagDialog::buttonBoxRejected()
|
||||
{
|
||||
close();
|
||||
this->setResult(QDialog::Rejected);
|
||||
}
|
||||
|
@ -19,12 +19,14 @@ public:
|
||||
~FlagDialog();
|
||||
|
||||
private slots:
|
||||
void on_buttonBox_accepted();
|
||||
void on_buttonBox_rejected();
|
||||
void buttonBoxAccepted();
|
||||
void buttonBoxRejected();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui::FlagDialog> ui;
|
||||
RVA offset;
|
||||
QString flagName;
|
||||
ut64 flagOffset;
|
||||
};
|
||||
|
||||
#endif // FLAGDIALOG_H
|
||||
|
@ -14,13 +14,20 @@
|
||||
<string>Add Flag</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelAction">
|
||||
<property name="text">
|
||||
<string>Add flag at</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="horizontalSpacing">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<widget class="QLabel" name="labelFlag">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
@ -62,7 +69,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<widget class="QLabel" name="labelSize">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
@ -89,38 +96,5 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>FlagDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>FlagDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -32,11 +32,9 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow *main
|
||||
actionCopy(this),
|
||||
actionCopyAddr(this),
|
||||
actionAddComment(this),
|
||||
actionAddFlag(this),
|
||||
actionAnalyzeFunction(this),
|
||||
actionEditFunction(this),
|
||||
actionRename(this),
|
||||
actionRenameUsedHere(this),
|
||||
actionSetFunctionVarTypes(this),
|
||||
actionXRefs(this),
|
||||
actionXRefsForVariables(this),
|
||||
@ -87,26 +85,18 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow *main
|
||||
SLOT(on_actionAddComment_triggered()), getCommentSequence());
|
||||
addAction(&actionAddComment);
|
||||
|
||||
initAction(&actionAddFlag, tr("Add Flag"),
|
||||
SLOT(on_actionAddFlag_triggered()), getAddFlagSequence());
|
||||
addAction(&actionAddFlag);
|
||||
|
||||
initAction(&actionRename, tr("Rename"),
|
||||
initAction(&actionRename, tr("Rename or add flag"),
|
||||
SLOT(on_actionRename_triggered()), getRenameSequence());
|
||||
addAction(&actionRename);
|
||||
|
||||
initAction(&actionEditFunction, tr("Edit function"),
|
||||
SLOT(on_actionEditFunction_triggered()), getEditFunctionSequence());
|
||||
addAction(&actionEditFunction);
|
||||
|
||||
initAction(&actionRenameUsedHere, tr("Rename Flag/Fcn/Var Used Here"),
|
||||
SLOT(on_actionRenameUsedHere_triggered()), getRenameUsedHereSequence());
|
||||
addAction(&actionRenameUsedHere);
|
||||
|
||||
initAction(&actionSetFunctionVarTypes, tr("Re-type Local Variables"),
|
||||
SLOT(on_actionSetFunctionVarTypes_triggered()), getRetypeSequence());
|
||||
addAction(&actionSetFunctionVarTypes);
|
||||
|
||||
initAction(&actionEditFunction, tr("Edit function"),
|
||||
SLOT(on_actionEditFunction_triggered()), getEditFunctionSequence());
|
||||
addAction(&actionEditFunction);
|
||||
|
||||
initAction(&actionDeleteComment, tr("Delete comment"), SLOT(on_actionDeleteComment_triggered()));
|
||||
addAction(&actionDeleteComment);
|
||||
|
||||
@ -361,44 +351,9 @@ QVector<DisassemblyContextMenu::ThingUsedHere> DisassemblyContextMenu::getThingU
|
||||
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;
|
||||
|
||||
this->actionSetFunctionVarTypes.setVisible(true);
|
||||
}
|
||||
|
||||
@ -410,6 +365,123 @@ void DisassemblyContextMenu::setCanCopy(bool enabled)
|
||||
void DisassemblyContextMenu::setCurHighlightedWord(const QString &text)
|
||||
{
|
||||
this->curHighlightedWord = text;
|
||||
// Update the renaming options only when a new word is selected
|
||||
setupRenaming();
|
||||
}
|
||||
|
||||
DisassemblyContextMenu::ThingUsedHere DisassemblyContextMenu::getThingAt(ut64 address)
|
||||
{
|
||||
ThingUsedHere tuh;
|
||||
RAnalFunction *fcn = Core()->functionAt(address);
|
||||
RFlagItem *flag = r_flag_get_i(Core()->core()->flags, address);
|
||||
|
||||
// We will lookup through existing r2 types to find something relevant
|
||||
|
||||
if (fcn != nullptr) {
|
||||
// It is a function
|
||||
tuh.type = ThingUsedHere::Type::Function;
|
||||
tuh.name = fcn->name;
|
||||
} else if (flag != nullptr) {
|
||||
// It is a flag
|
||||
tuh.type = ThingUsedHere::Type::Flag;
|
||||
if (Config()->getConfigBool("asm.flags.real") && flag->realname) {
|
||||
tuh.name = flag->realname;
|
||||
} else {
|
||||
tuh.name = flag->name;
|
||||
}
|
||||
} else {
|
||||
// Consider it an address
|
||||
tuh.type = ThingUsedHere::Type::Address;
|
||||
}
|
||||
|
||||
tuh.offset = address;
|
||||
return tuh;
|
||||
}
|
||||
|
||||
void DisassemblyContextMenu::buildRenameMenu(ThingUsedHere* tuh)
|
||||
{
|
||||
if (!tuh) {
|
||||
qWarning() << "Unexpected behavior null pointer passed to DisassemblyContextMenu::buildRenameMenu";
|
||||
doRenameAction = RENAME_DO_NOTHING;
|
||||
return;
|
||||
}
|
||||
|
||||
actionDeleteFlag.setVisible(false);
|
||||
if (tuh->type == ThingUsedHere::Type::Address) {
|
||||
doRenameAction = RENAME_ADD_FLAG;
|
||||
doRenameInfo.name = RAddressString(tuh->offset);
|
||||
doRenameInfo.addr = tuh->offset;
|
||||
actionRename.setText(tr("Add flag at %1 (used here)").arg(doRenameInfo.name));
|
||||
} else if (tuh->type == ThingUsedHere::Type::Function) {
|
||||
doRenameAction = RENAME_FUNCTION;
|
||||
doRenameInfo.name = tuh->name;
|
||||
doRenameInfo.addr = tuh->offset;
|
||||
actionRename.setText(tr("Rename \"%1\"").arg(doRenameInfo.name));
|
||||
} else if (tuh->type == ThingUsedHere::Type::Var) {
|
||||
doRenameAction = RENAME_LOCAL;
|
||||
doRenameInfo.name = tuh->name;
|
||||
doRenameInfo.addr = tuh->offset;
|
||||
actionRename.setText(tr("Rename local \"%1\"").arg(tuh->name));
|
||||
} else if (tuh->type == ThingUsedHere::Type::Flag) {
|
||||
doRenameAction = RENAME_FLAG;
|
||||
doRenameInfo.name = tuh->name;
|
||||
doRenameInfo.addr = tuh->offset;
|
||||
actionRename.setText(tr("Rename flag \"%1\" (used here)").arg(doRenameInfo.name));
|
||||
actionDeleteFlag.setVisible(true);
|
||||
} else {
|
||||
qWarning() << "Unexpected renaming type";
|
||||
doRenameAction = RENAME_DO_NOTHING;
|
||||
}
|
||||
}
|
||||
|
||||
void DisassemblyContextMenu::setupRenaming()
|
||||
{
|
||||
// We parse our highlighted word as an address
|
||||
ut64 selection = Core()->num(curHighlightedWord);
|
||||
|
||||
// First, let's try to see if current line (offset) contains a local variable or a function
|
||||
ThingUsedHere *tuh = nullptr;
|
||||
ThingUsedHere thingAt;
|
||||
auto things = getThingUsedHere(offset);
|
||||
for (auto& thing : things) {
|
||||
if (thing.offset == selection || thing.name == curHighlightedWord) {
|
||||
// We matched something on current line
|
||||
tuh = &thing;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tuh) {
|
||||
// Nothing matched on current line, is there anything valid coming from our selection?
|
||||
thingAt = getThingAt(selection);
|
||||
|
||||
if (thingAt.offset == 0) {
|
||||
// We parsed something which resolved to 0, it's very likely nothing interesting was selected
|
||||
// So we fallback on current line offset
|
||||
thingAt = getThingAt(offset);
|
||||
}
|
||||
|
||||
// However, since for the moment selection selects *every* lines which match a specific offset,
|
||||
// make sure we didn't want to select a local variable rather than the function itself
|
||||
if (thingAt.type == ThingUsedHere::Type::Function) {
|
||||
auto vars = Core()->getVariables(offset);
|
||||
for (auto v : vars) {
|
||||
if (v.name == curHighlightedWord) {
|
||||
// This is a local variable
|
||||
thingAt.type = ThingUsedHere::Type::Var;
|
||||
thingAt.name = v.name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In any case, thingAt will contain something we can rename
|
||||
tuh = &thingAt;
|
||||
}
|
||||
|
||||
// Now, build the renaming menu and show it
|
||||
buildRenameMenu(tuh);
|
||||
actionRename.setVisible(true);
|
||||
}
|
||||
|
||||
void DisassemblyContextMenu::aboutToShowSlot()
|
||||
@ -483,36 +555,12 @@ void DisassemblyContextMenu::aboutToShowSlot()
|
||||
actionCopy.setVisible(canCopy);
|
||||
copySeparator->setVisible(canCopy);
|
||||
|
||||
|
||||
RCore *core = Core()->core();
|
||||
RAnalFunction *fcn = Core()->functionAt(offset);
|
||||
RAnalFunction *in_fcn = Core()->functionIn(offset);
|
||||
RFlagItem *f = r_flag_get_i (core->flags, offset);
|
||||
|
||||
actionDeleteFlag.setVisible(f ? true : false);
|
||||
actionDeleteFunction.setVisible(fcn ? true : false);
|
||||
|
||||
if (fcn) {
|
||||
actionAnalyzeFunction.setVisible(false);
|
||||
actionRename.setVisible(true);
|
||||
actionRename.setText(tr("Rename function \"%1\"").arg(fcn->name));
|
||||
} else if (f) {
|
||||
QString name;
|
||||
|
||||
// Check if Realname is enabled. If yes, show it instead of the full flag-name.
|
||||
if (Config()->getConfigBool("asm.flags.real") && f->realname) {
|
||||
name = f->realname;
|
||||
} else {
|
||||
name = f->name;
|
||||
}
|
||||
|
||||
actionRename.setVisible(true);
|
||||
actionRename.setText(tr("Rename flag \"%1\"").arg(name));
|
||||
} else {
|
||||
actionRename.setVisible(false);
|
||||
}
|
||||
// Handle renaming of variable, function, flag, ...
|
||||
// Note: This might be useless if we consider setCurrentHighlightedWord is always called before
|
||||
setupRenaming();
|
||||
|
||||
// Only show retype for local vars if in a function
|
||||
RAnalFunction *in_fcn = Core()->functionIn(offset);
|
||||
if (in_fcn) {
|
||||
auto vars = Core()->getVariables(offset);
|
||||
actionSetFunctionVarTypes.setVisible(!vars.empty());
|
||||
@ -523,25 +571,6 @@ void DisassemblyContextMenu::aboutToShowSlot()
|
||||
actionEditFunction.setVisible(false);
|
||||
}
|
||||
|
||||
|
||||
// Only show "rename X used here" if there is something to rename
|
||||
auto thingsUsedHere = getThingUsedHere(offset);
|
||||
if (!thingsUsedHere.isEmpty()) {
|
||||
actionRenameUsedHere.setVisible(true);
|
||||
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 == 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();
|
||||
|
||||
@ -619,21 +648,11 @@ QKeySequence DisassemblyContextMenu::getSetToDataExSequence() const
|
||||
return {Qt::Key_Asterisk};
|
||||
}
|
||||
|
||||
QKeySequence DisassemblyContextMenu::getAddFlagSequence() const
|
||||
{
|
||||
return {}; //TODO insert correct sequence
|
||||
}
|
||||
|
||||
QKeySequence DisassemblyContextMenu::getRenameSequence() const
|
||||
{
|
||||
return {Qt::Key_N};
|
||||
}
|
||||
|
||||
QKeySequence DisassemblyContextMenu::getRenameUsedHereSequence() const
|
||||
{
|
||||
return {Qt::SHIFT | Qt::Key_N};
|
||||
}
|
||||
|
||||
QKeySequence DisassemblyContextMenu::getRetypeSequence() const
|
||||
{
|
||||
return {Qt::Key_Y};
|
||||
@ -803,77 +822,37 @@ void DisassemblyContextMenu::on_actionAnalyzeFunction_triggered()
|
||||
}
|
||||
}
|
||||
|
||||
void DisassemblyContextMenu::on_actionAddFlag_triggered()
|
||||
{
|
||||
FlagDialog dialog(offset, this->parentWidget());
|
||||
dialog.exec();
|
||||
}
|
||||
|
||||
void DisassemblyContextMenu::on_actionRename_triggered()
|
||||
{
|
||||
RCore *core = Core()->core();
|
||||
bool ok;
|
||||
|
||||
RAnalFunction *fcn = Core()->functionIn(offset);
|
||||
RFlagItem *f = r_flag_get_i(core->flags, offset);
|
||||
|
||||
if (fcn) {
|
||||
// Renaming a function
|
||||
QString newName = QInputDialog::getText(this->mainWindow, tr("Rename function %2").arg(fcn->name),
|
||||
tr("Function name:"), QLineEdit::Normal, fcn->name, &ok);
|
||||
bool ok = false;
|
||||
if (doRenameAction == RENAME_FUNCTION) {
|
||||
QString newName = QInputDialog::getText(this->mainWindow, tr("Rename function %2").arg(doRenameInfo.name),
|
||||
tr("Function name:"), QLineEdit::Normal, doRenameInfo.name, &ok);
|
||||
if (ok && !newName.isEmpty()) {
|
||||
Core()->renameFunction(fcn->addr, newName);
|
||||
Core()->renameFunction(doRenameInfo.addr, newName);
|
||||
}
|
||||
} else if (f) {
|
||||
// Renaming flag
|
||||
QString newName = QInputDialog::getText(this, tr("Rename flag %2").arg(f->name),
|
||||
tr("Flag name:"), QLineEdit::Normal, f->name, &ok);
|
||||
if (ok && !newName.isEmpty()) {
|
||||
Core()->renameFlag(f->name, newName);
|
||||
} else if (doRenameAction == RENAME_FLAG || doRenameAction == RENAME_ADD_FLAG) {
|
||||
FlagDialog dialog(doRenameInfo.addr, this->mainWindow);
|
||||
ok = dialog.exec();
|
||||
} else if (doRenameAction == RENAME_LOCAL) {
|
||||
RAnalFunction *fcn = Core()->functionIn(offset);
|
||||
if (fcn) {
|
||||
EditVariablesDialog dialog(fcn->addr, curHighlightedWord, this->mainWindow);
|
||||
if (!dialog.empty()) {
|
||||
// Don't show the dialog if there are no variables
|
||||
ok = dialog.exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DisassemblyContextMenu::on_actionRenameUsedHere_triggered()
|
||||
{
|
||||
|
||||
QString title;
|
||||
QString inputValue;
|
||||
QString oldName;
|
||||
|
||||
auto array = getThingUsedHere(offset);
|
||||
if (array.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto thingUsedHere = array.first();
|
||||
auto type = thingUsedHere.type;
|
||||
|
||||
if (type == ThingUsedHere::Type::Address) {
|
||||
RVA offset = thingUsedHere.offset;
|
||||
title = tr("Add flag at %1").arg(RAddressString(offset));
|
||||
inputValue = "label." + QString::number(offset, 16);
|
||||
} else if (doRenameAction == RENAME_DO_NOTHING) {
|
||||
// Do nothing
|
||||
} else {
|
||||
oldName = thingUsedHere.name;
|
||||
title = tr("Rename %1").arg(oldName);
|
||||
inputValue = oldName;
|
||||
qWarning() << "Unhandled renaming action: " << doRenameAction;
|
||||
assert(false);
|
||||
}
|
||||
|
||||
bool ok;
|
||||
// Create dialog
|
||||
QString newName = QInputDialog::getText(this, title,
|
||||
tr("Name:"), QLineEdit::Normal, inputValue, &ok);
|
||||
|
||||
// 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(thingUsedHere.offset, newName);
|
||||
}
|
||||
if (ok) {
|
||||
// Rebuild menu in case the user presses the rename shortcut directly before clicking
|
||||
setupRenaming();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,9 +44,7 @@ private slots:
|
||||
void on_actionCopyAddr_triggered();
|
||||
void on_actionAddComment_triggered();
|
||||
void on_actionAnalyzeFunction_triggered();
|
||||
void on_actionAddFlag_triggered();
|
||||
void on_actionRename_triggered();
|
||||
void on_actionRenameUsedHere_triggered();
|
||||
void on_actionSetFunctionVarTypes_triggered();
|
||||
void on_actionXRefs_triggered();
|
||||
void on_actionXRefsForVariables_triggered();
|
||||
@ -92,9 +90,7 @@ private:
|
||||
QKeySequence getSetAsStringAdvanced() const;
|
||||
QKeySequence getSetToDataSequence() const;
|
||||
QKeySequence getSetToDataExSequence() const;
|
||||
QKeySequence getAddFlagSequence() const;
|
||||
QKeySequence getRenameSequence() const;
|
||||
QKeySequence getRenameUsedHereSequence() const;
|
||||
QKeySequence getRetypeSequence() const;
|
||||
QKeySequence getXRefSequence() const;
|
||||
QKeySequence getDisplayOptionsSequence() const;
|
||||
@ -129,11 +125,9 @@ private:
|
||||
|
||||
|
||||
QAction actionAddComment;
|
||||
QAction actionAddFlag;
|
||||
QAction actionAnalyzeFunction;
|
||||
QAction actionEditFunction;
|
||||
QAction actionRename;
|
||||
QAction actionRenameUsedHere;
|
||||
QAction actionSetFunctionVarTypes;
|
||||
QAction actionXRefs;
|
||||
QAction actionXRefsForVariables;
|
||||
@ -209,6 +203,29 @@ private:
|
||||
void addBreakpointMenu();
|
||||
void addDebugMenu();
|
||||
|
||||
enum DoRenameAction {
|
||||
RENAME_FUNCTION,
|
||||
RENAME_FLAG,
|
||||
RENAME_ADD_FLAG,
|
||||
RENAME_LOCAL,
|
||||
RENAME_DO_NOTHING,
|
||||
};
|
||||
struct DoRenameInfo {
|
||||
ut64 addr;
|
||||
QString name;
|
||||
};
|
||||
DoRenameAction doRenameAction = RENAME_DO_NOTHING;
|
||||
DoRenameInfo doRenameInfo = { };
|
||||
|
||||
/*
|
||||
* @brief Setups up the "Rename" option in the context menu
|
||||
*
|
||||
* This function takes into account cursor location so it can choose between current address and pointed value
|
||||
* i.e. `0x000040f3 lea rdi, [0x000199b1]` -> does the user want to add a flag at 0x40f3 or at 0x199b1?
|
||||
* and for that we will rely on |curHighlightedWord| which is the currently selected word.
|
||||
*/
|
||||
void setupRenaming();
|
||||
|
||||
/**
|
||||
* @brief Checks if the currently highlighted word in the disassembly widget
|
||||
* is a local variable or function paramter.
|
||||
@ -229,6 +246,20 @@ private:
|
||||
};
|
||||
QVector<ThingUsedHere> getThingUsedHere(RVA offset);
|
||||
|
||||
void updateTargetMenuActions(const QVector<ThingUsedHere> &targets);
|
||||
/*
|
||||
* @brief This function checks if the given address contains a function,
|
||||
* a flag or if it is just an address.
|
||||
*/
|
||||
ThingUsedHere getThingAt(ut64 address);
|
||||
|
||||
/*
|
||||
* @brief This function will set the text for the renaming menu given a ThingUsedHere
|
||||
* and provide information on how to handle the renaming of this specific thing.
|
||||
* Indeed, selected dialogs are different when it comes to adding a flag, renaming an existing function,
|
||||
* renaming a local variable...
|
||||
*
|
||||
* This function handles every possible object.
|
||||
*/
|
||||
void buildRenameMenu(ThingUsedHere* tuh);
|
||||
};
|
||||
#endif // DISASSEMBLYCONTEXTMENU_H
|
||||
|
Loading…
Reference in New Issue
Block a user