cutter/src/menus/DisassemblyContextMenu.cpp

747 lines
23 KiB
C++
Raw Normal View History

#include "DisassemblyContextMenu.h"
#include "dialogs/preferences/PreferencesDialog.h"
#include "dialogs/EditInstructionDialog.h"
#include "dialogs/CommentsDialog.h"
#include "dialogs/FlagDialog.h"
#include "dialogs/RenameDialog.h"
#include "dialogs/XrefsDialog.h"
#include "dialogs/SetFunctionVarTypes.h"
2018-08-04 18:05:56 +00:00
#include "dialogs/SetToDataDialog.h"
#include <QtCore>
#include <QShortcut>
#include <QJsonArray>
#include <QClipboard>
#include <QApplication>
2017-11-19 17:49:29 +00:00
DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent)
: QMenu(parent),
offset(0),
2018-08-04 18:05:56 +00:00
canCopy(false)
{
initAction(&actionCopy, tr("Copy"), SLOT(on_actionCopy_triggered()), getCopySequence());
addAction(&actionCopy);
2017-12-02 15:43:21 +00:00
copySeparator = addSeparator();
2018-08-04 18:05:56 +00:00
2018-08-15 21:31:01 +00:00
initAction(&actionCopyAddr, tr("Copy address"), SLOT(on_actionCopyAddr_triggered()));
2018-08-04 18:05:56 +00:00
addAction(&actionCopyAddr);
initAction(&actionAddComment, tr("Add Comment"),
SLOT(on_actionAddComment_triggered()), getCommentSequence());
addAction(&actionAddComment);
initAction(&actionAddFlag, tr("Add Flag"),
SLOT(on_actionAddFlag_triggered()), getAddFlagSequence());
addAction(&actionAddFlag);
initAction(&actionRename, tr("Rename"),
SLOT(on_actionRename_triggered()), getRenameSequence());
addAction(&actionRename);
initAction(&actionRenameUsedHere, tr("Rename Flag/Fcn/Var Used Here"),
SLOT(on_actionRenameUsedHere_triggered()), getRenameUsedHereSequence());
addAction(&actionRenameUsedHere);
initAction(&actionSetFunctionVarTypes, tr("Re-type function local vars"),
SLOT(on_actionSetFunctionVarTypes_triggered()), getRetypeSequence());
addAction(&actionSetFunctionVarTypes);
2018-08-04 18:05:56 +00:00
initAction(&actionDeleteComment, tr("Delete comment"), SLOT(on_actionDeleteComment_triggered()));
addAction(&actionDeleteComment);
initAction(&actionDeleteFlag, tr("Delete flag"), SLOT(on_actionDeleteFlag_triggered()));
addAction(&actionDeleteFlag);
2018-09-26 12:43:37 +00:00
initAction(&actionDeleteFunction, tr("Undefine function"),
SLOT(on_actionDeleteFunction_triggered()));
2018-08-04 18:05:56 +00:00
addAction(&actionDeleteFunction);
2018-09-26 12:43:37 +00:00
initAction(&actionAnalyzeFunction, tr("Define function here..."),
SLOT(on_actionAnalyzeFunction_triggered()));
addAction(&actionAnalyzeFunction);
2018-08-04 18:05:56 +00:00
addSetBaseMenu();
addSetBitsMenu();
initAction(&actionSetToCode, tr("Set to Code"),
SLOT(on_actionSetToCode_triggered()), getSetToCodeSequence());
addAction(&actionSetToCode);
addSetToDataMenu();
addSeparator();
initAction(&actionXRefs, tr("Show X-Refs"),
SLOT(on_actionXRefs_triggered()), getXRefSequence());
addAction(&actionXRefs);
initAction(&actionDisplayOptions, tr("Show Options"),
SLOT(on_actionDisplayOptions_triggered()), getDisplayOptionsSequence());
addSeparator();
addEditMenu();
addSeparator();
addDebugMenu();
connect(this, &DisassemblyContextMenu::aboutToShow,
this, &DisassemblyContextMenu::aboutToShowSlot);
}
DisassemblyContextMenu::~DisassemblyContextMenu()
{
for (QAction *action : anonymousActions) {
delete action;
}
}
void DisassemblyContextMenu::addSetBaseMenu()
{
setBaseMenu = addMenu(tr("Set Immediate Base to..."));
initAction(&actionSetBaseBinary, tr("Binary"));
2017-11-28 13:50:41 +00:00
setBaseMenu->addAction(&actionSetBaseBinary);
2018-08-04 18:05:56 +00:00
connect(&actionSetBaseBinary, &QAction::triggered, this, [this] { setBase("b"); });
initAction(&actionSetBaseOctal, tr("Octal"));
2017-11-28 13:50:41 +00:00
setBaseMenu->addAction(&actionSetBaseOctal);
2018-08-04 18:05:56 +00:00
connect(&actionSetBaseOctal, &QAction::triggered, this, [this] { setBase("o"); });
initAction(&actionSetBaseDecimal, tr("Decimal"));
2017-11-28 13:50:41 +00:00
setBaseMenu->addAction(&actionSetBaseDecimal);
2018-08-04 18:05:56 +00:00
connect(&actionSetBaseDecimal, &QAction::triggered, this, [this] { setBase("d"); });
initAction(&actionSetBaseHexadecimal, tr("Hexadecimal"));
2017-11-28 13:50:41 +00:00
setBaseMenu->addAction(&actionSetBaseHexadecimal);
2018-08-04 18:05:56 +00:00
connect(&actionSetBaseHexadecimal, &QAction::triggered, this, [this] { setBase("h"); });
initAction(&actionSetBasePort, tr("Network Port"));
2017-11-28 13:50:41 +00:00
setBaseMenu->addAction(&actionSetBasePort);
2018-08-04 18:05:56 +00:00
connect(&actionSetBasePort, &QAction::triggered, this, [this] { setBase("p"); });
initAction(&actionSetBaseIPAddr, tr("IP Address"));
2017-11-28 13:50:41 +00:00
setBaseMenu->addAction(&actionSetBaseIPAddr);
2018-08-04 18:05:56 +00:00
connect(&actionSetBaseIPAddr, &QAction::triggered, this, [this] { setBase("i"); });
initAction(&actionSetBaseSyscall, tr("Syscall"));
2017-11-28 13:50:41 +00:00
setBaseMenu->addAction(&actionSetBaseSyscall);
2018-08-04 18:05:56 +00:00
connect(&actionSetBaseSyscall, &QAction::triggered, this, [this] { setBase("S"); });
initAction(&actionSetBaseString, tr("String"));
2017-11-28 13:50:41 +00:00
setBaseMenu->addAction(&actionSetBaseString);
2018-08-04 18:05:56 +00:00
connect(&actionSetBaseString, &QAction::triggered, this, [this] { setBase("s"); });
}
void DisassemblyContextMenu::addSetBitsMenu()
{
setBitsMenu = addMenu(tr("Set current bits to..."));
2018-02-12 09:48:06 +00:00
2018-08-04 18:05:56 +00:00
initAction(&actionSetBits16, "16");
2018-02-12 09:48:06 +00:00
setBitsMenu->addAction(&actionSetBits16);
2018-08-04 18:05:56 +00:00
connect(&actionSetBits16, &QAction::triggered, this, [this] { setBits(16); });
initAction(&actionSetBits32, "32");
2018-02-12 09:48:06 +00:00
setBitsMenu->addAction(&actionSetBits32);
2018-08-04 18:05:56 +00:00
connect(&actionSetBits32, &QAction::triggered, this, [this] { setBits(32); });
initAction(&actionSetBits64, "64");
2018-02-12 09:48:06 +00:00
setBitsMenu->addAction(&actionSetBits64);
2018-08-04 18:05:56 +00:00
connect(&actionSetBits64, &QAction::triggered, this, [this] { setBits(64); });
}
2018-02-12 09:48:06 +00:00
2018-08-04 18:05:56 +00:00
void DisassemblyContextMenu::addSetToDataMenu()
{
setToDataMenu = addMenu(tr("Set to Data..."));
2018-08-04 18:05:56 +00:00
initAction(&actionSetToDataByte, tr("Byte"));
setToDataMenu->addAction(&actionSetToDataByte);
connect(&actionSetToDataByte, &QAction::triggered, this, [this] { setToData(1); });
initAction(&actionSetToDataWord, tr("Word"));
setToDataMenu->addAction(&actionSetToDataWord);
connect(&actionSetToDataWord, &QAction::triggered, this, [this] { setToData(2); });
initAction(&actionSetToDataDword, tr("Dword"));
setToDataMenu->addAction(&actionSetToDataDword);
connect(&actionSetToDataDword, &QAction::triggered, this, [this] { setToData(4); });
initAction(&actionSetToDataQword, tr("Qword"));
setToDataMenu->addAction(&actionSetToDataQword);
connect(&actionSetToDataQword, &QAction::triggered, this, [this] { setToData(8); });
initAction(&actionSetToDataEx, "...",
SLOT(on_actionSetToDataEx_triggered()), getSetToDataExSequence());
setToDataMenu->addAction(&actionSetToDataEx);
auto switchAction = new QAction();
initAction(switchAction, "Switch Data",
SLOT(on_actionSetToData_triggered()), getSetToDataSequence());
}
void DisassemblyContextMenu::addEditMenu()
{
editMenu = addMenu(tr("Edit"));
initAction(&actionEditInstruction, tr("Instruction"), SLOT(on_actionEditInstruction_triggered()));
editMenu->addAction(&actionEditInstruction);
2018-08-04 18:05:56 +00:00
initAction(&actionNopInstruction, tr("Nop Instruction"), SLOT(on_actionNopInstruction_triggered()));
editMenu->addAction(&actionNopInstruction);
2018-08-04 18:05:56 +00:00
initAction(&actionEditBytes, tr("Bytes"), SLOT(on_actionEditBytes_triggered()));
editMenu->addAction(&actionEditBytes);
2018-06-12 08:43:14 +00:00
2018-08-04 18:05:56 +00:00
initAction(&actionJmpReverse, tr("Reverse Jump"), SLOT(on_actionJmpReverse_triggered()));
editMenu->addAction(&actionJmpReverse);
2017-11-28 13:50:41 +00:00
}
2018-08-04 18:05:56 +00:00
void DisassemblyContextMenu::addDebugMenu()
{
2018-08-04 18:05:56 +00:00
debugMenu = addMenu(tr("Debug"));
initAction(&actionAddBreakpoint, tr("Add/remove breakpoint"),
SLOT(on_actionAddBreakpoint_triggered()), getAddBPSequence());
debugMenu->addAction(&actionAddBreakpoint);
initAction(&actionContinueUntil, tr("Continue until line"),
SLOT(on_actionContinueUntil_triggered()));
debugMenu->addAction(&actionContinueUntil);
initAction(&actionSetPC, "Set PC", SLOT(on_actionSetPC_triggered()));
debugMenu->addAction(&actionSetPC);
}
2017-11-28 13:50:41 +00:00
void DisassemblyContextMenu::setOffset(RVA offset)
{
this->offset = offset;
}
2017-12-02 15:43:21 +00:00
void DisassemblyContextMenu::setCanCopy(bool enabled)
{
this->canCopy = enabled;
}
2017-11-28 13:50:41 +00:00
void DisassemblyContextMenu::aboutToShowSlot()
{
// check if set immediate base menu makes sense
2018-03-21 20:32:32 +00:00
QJsonObject instObject = Core()->cmdj("aoj @ " + QString::number(
offset)).array().first().toObject();
2017-11-28 13:50:41 +00:00
auto keys = instObject.keys();
bool immBase = keys.contains("val") || keys.contains("ptr");
2018-08-04 18:05:56 +00:00
setBaseMenu->menuAction()->setVisible(immBase);
setBitsMenu->menuAction()->setVisible(true);
actionAnalyzeFunction.setVisible(true);
QString comment = Core()->cmd("CC." + RAddressString(offset));
2018-03-21 20:32:32 +00:00
if (comment.isNull() || comment.isEmpty()) {
actionDeleteComment.setVisible(false);
actionAddComment.setText(tr("Add Comment"));
2018-03-21 20:32:32 +00:00
} else {
actionDeleteComment.setVisible(true);
actionAddComment.setText(tr("Edit Comment"));
}
2017-12-02 15:43:21 +00:00
actionCopy.setVisible(canCopy);
copySeparator->setVisible(canCopy);
RCore *core = Core()->core();
RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, offset, R_ANAL_FCN_TYPE_NULL);
RAnalFunction *in_fcn = Core()->functionAt(offset);
RFlagItem *f = r_flag_get_i (core->flags, offset);
actionDeleteFlag.setVisible(f ? true : false);
actionDeleteFunction.setVisible(fcn ? true : false);
2018-03-21 20:32:32 +00:00
if (fcn) {
actionAnalyzeFunction.setVisible(false);
actionRename.setVisible(true);
actionRename.setText(tr("Rename function \"%1\"").arg(fcn->name));
2018-03-21 20:32:32 +00:00
} else if (f) {
actionRename.setVisible(true);
actionRename.setText(tr("Rename flag \"%1\"").arg(f->name));
2018-03-21 20:32:32 +00:00
} else {
actionRename.setVisible(false);
}
2017-11-30 14:16:39 +00:00
//only show retype for local vars if in a function
if(in_fcn)
{
actionSetFunctionVarTypes.setVisible(true);
}
else
{
actionSetFunctionVarTypes.setVisible(false);
}
2017-11-30 14:16:39 +00:00
// only show "rename X used here" if there is something to rename
2017-11-30 21:18:09 +00:00
QJsonArray thingUsedHereArray = Core()->cmdj("anj @ " + QString::number(offset)).array();
2018-03-21 20:32:32 +00:00
if (!thingUsedHereArray.isEmpty()) {
2017-11-30 14:16:39 +00:00
actionRenameUsedHere.setVisible(true);
2017-11-30 21:18:09 +00:00
QJsonObject thingUsedHere = thingUsedHereArray.first().toObject();
2018-03-21 20:32:32 +00:00
if (thingUsedHere["type"] == "address") {
2017-11-30 21:18:09 +00:00
RVA offset = thingUsedHere["offset"].toVariant().toULongLong();
actionRenameUsedHere.setText(tr("Add flag at %1 (used here)").arg(RAddressString(offset)));
2018-03-21 20:32:32 +00:00
} else {
2017-11-30 21:18:09 +00:00
actionRenameUsedHere.setText(tr("Rename \"%1\" (used here)").arg(thingUsedHere["name"].toString()));
}
2018-03-21 20:32:32 +00:00
} else {
2017-11-30 14:16:39 +00:00
actionRenameUsedHere.setVisible(false);
}
// decide to show Reverse jmp option
showReverseJmpQuery();
// only show debug options if we are currently debugging
2018-08-04 18:05:56 +00:00
debugMenu->menuAction()->setVisible(Core()->currentlyDebugging);
QString progCounterName = Core()->getRegisterName("PC");
actionSetPC.setText("Set " + progCounterName + " here");
2017-12-02 15:43:21 +00:00
}
QKeySequence DisassemblyContextMenu::getCopySequence() const
{
return QKeySequence::Copy;
2017-11-28 13:50:41 +00:00
}
QKeySequence DisassemblyContextMenu::getCommentSequence() const
{
2018-01-16 14:29:33 +00:00
return {Qt::Key_Semicolon};
2017-11-28 13:50:41 +00:00
}
2018-08-04 18:05:56 +00:00
QKeySequence DisassemblyContextMenu::getSetToCodeSequence() const
{
return {Qt::Key_C};
}
QKeySequence DisassemblyContextMenu::getSetToDataSequence() const
{
return {Qt::Key_D};
}
QKeySequence DisassemblyContextMenu::getSetToDataExSequence() const
{
return {Qt::Key_Asterisk};
}
2017-11-28 13:50:41 +00:00
QKeySequence DisassemblyContextMenu::getAddFlagSequence() const
{
return {}; //TODO insert correct sequence
}
QKeySequence DisassemblyContextMenu::getRenameSequence() const
{
return {Qt::Key_N};
}
2017-11-30 14:16:39 +00:00
QKeySequence DisassemblyContextMenu::getRenameUsedHereSequence() const
{
return {Qt::SHIFT + Qt::Key_N};
}
QKeySequence DisassemblyContextMenu::getRetypeSequence() const
{
return {Qt::Key_Y};
}
2017-11-28 13:50:41 +00:00
QKeySequence DisassemblyContextMenu::getXRefSequence() const
{
return {Qt::Key_X};
}
QKeySequence DisassemblyContextMenu::getDisplayOptionsSequence() const
{
return {}; //TODO insert correct sequence
}
QList<QKeySequence> DisassemblyContextMenu::getAddBPSequence() const
{
return {Qt::Key_F2, Qt::CTRL + Qt::Key_B};
}
void DisassemblyContextMenu::on_actionEditInstruction_triggered()
{
EditInstructionDialog *e = new EditInstructionDialog(this, false);
e->setWindowTitle(tr("Edit Instruction at %1").arg(RAddressString(offset)));
QString oldInstructionOpcode = Core()->getInstructionOpcode(offset);
QString oldInstructionBytes = Core()->getInstructionBytes(offset);
e->setInstruction(oldInstructionOpcode);
2018-09-26 12:43:37 +00:00
if (e->exec()) {
QString userInstructionOpcode = e->getInstruction();
if (userInstructionOpcode != oldInstructionOpcode) {
Core()->editInstruction(offset, userInstructionOpcode);
// check if the write failed
auto newInstructionBytes = Core()->getInstructionBytes(offset);
if (newInstructionBytes == oldInstructionBytes) {
writeFailed();
}
}
}
}
void DisassemblyContextMenu::on_actionNopInstruction_triggered()
{
QString oldBytes = Core()->getInstructionBytes(offset);
Core()->nopInstruction(offset);
QString newBytes = Core()->getInstructionBytes(offset);
if (oldBytes == newBytes) {
writeFailed();
}
}
void DisassemblyContextMenu::showReverseJmpQuery()
{
QString type;
QJsonArray array = Core()->cmdj("pdj 1 @ " + RAddressString(offset)).array();
2018-03-21 20:32:32 +00:00
if (array.isEmpty()) {
return;
}
type = array.first().toObject()["type"].toString();
2018-03-21 20:32:32 +00:00
if (type == "cjmp") {
actionJmpReverse.setVisible(true);
2018-03-21 20:32:32 +00:00
} else {
actionJmpReverse.setVisible(false);
}
}
void DisassemblyContextMenu::on_actionJmpReverse_triggered()
{
QString oldBytes = Core()->getInstructionBytes(offset);
Core()->jmpReverse(offset);
QString newBytes = Core()->getInstructionBytes(offset);
if (oldBytes == newBytes) {
writeFailed();
}
}
void DisassemblyContextMenu::on_actionEditBytes_triggered()
{
EditInstructionDialog *e = new EditInstructionDialog(this, true);
e->setWindowTitle(tr("Edit Bytes at %1").arg(RAddressString(offset)));
QString oldBytes = Core()->getInstructionBytes(offset);
e->setInstruction(oldBytes);
2018-09-26 12:43:37 +00:00
if (e->exec()) {
QString bytes = e->getInstruction();
2018-03-21 20:32:32 +00:00
if (bytes != oldBytes) {
Core()->editBytes(offset, bytes);
QString newBytes = Core()->getInstructionBytes(offset);
if (oldBytes == newBytes) {
writeFailed();
}
}
}
}
void DisassemblyContextMenu::writeFailed()
{
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Icon::Critical);
msgBox.setWindowTitle(tr("Write error"));
msgBox.setText(tr("Unable to complete write operation. Consider opening in write mode."));
msgBox.addButton(tr("OK"), QMessageBox::NoRole);
2018-09-26 12:43:37 +00:00
QAbstractButton *reopenButton = msgBox.addButton(tr("Reopen in write mode"), QMessageBox::YesRole);
msgBox.exec();
if (msgBox.clickedButton() == reopenButton) {
2018-09-26 12:43:37 +00:00
QMessageBox::warning(this, "File reopened in write mode",
"WARNING: Any chages will now be commited to disk");
Core()->cmd("oo+");
}
}
2017-12-02 15:43:21 +00:00
void DisassemblyContextMenu::on_actionCopy_triggered()
{
emit copy();
}
void DisassemblyContextMenu::on_actionCopyAddr_triggered()
{
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(RAddressString(offset));
}
2018-06-12 08:43:14 +00:00
void DisassemblyContextMenu::on_actionAddBreakpoint_triggered()
{
Core()->toggleBreakpoint(offset);
2018-06-12 08:43:14 +00:00
}
void DisassemblyContextMenu::on_actionContinueUntil_triggered()
{
Core()->continueUntilDebug(RAddressString(offset));
}
void DisassemblyContextMenu::on_actionSetPC_triggered()
{
QString progCounterName = Core()->getRegisterName("PC");
Core()->setRegister(progCounterName, RAddressString(offset));
}
void DisassemblyContextMenu::on_actionAddComment_triggered()
{
QString oldComment = Core()->cmd("CC." + RAddressString(offset));
// Remove newline at the end added by cmd
2018-03-21 20:32:32 +00:00
oldComment.remove(oldComment.length() - 1, 1);
CommentsDialog *c = new CommentsDialog(this);
2018-03-21 20:32:32 +00:00
if (oldComment.isNull() || oldComment.isEmpty()) {
c->setWindowTitle(tr("Add Comment at %1").arg(RAddressString(offset)));
2018-03-21 20:32:32 +00:00
} else {
c->setWindowTitle(tr("Edit Comment at %1").arg(RAddressString(offset)));
}
c->setComment(oldComment);
2018-03-21 20:32:32 +00:00
if (c->exec()) {
QString comment = c->getComment();
2018-03-21 20:32:32 +00:00
if (comment.isEmpty()) {
Core()->delComment(offset);
2018-03-21 20:32:32 +00:00
} else {
Core()->setComment(offset, comment);
}
}
}
void DisassemblyContextMenu::on_actionAnalyzeFunction_triggered()
{
RenameDialog *dialog = new RenameDialog(this);
dialog->setWindowTitle(tr("Analyze function at %1").arg(RAddressString(offset)));
2018-09-26 12:43:37 +00:00
dialog->setPlaceholderText(tr("Function name"));
2018-03-21 20:32:32 +00:00
if (dialog->exec()) {
QString function_name = dialog->getName();
Core()->createFunctionAt(offset, function_name);
}
}
void DisassemblyContextMenu::on_actionAddFlag_triggered()
{
FlagDialog *dialog = new FlagDialog(offset, this->parentWidget());
dialog->exec();
}
void DisassemblyContextMenu::on_actionRename_triggered()
{
2017-11-26 16:53:05 +00:00
RCore *core = Core()->core();
RenameDialog *dialog = new RenameDialog(this);
2017-11-26 16:53:05 +00:00
RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, offset, R_ANAL_FCN_TYPE_NULL);
RFlagItem *f = r_flag_get_i (core->flags, offset);
2018-03-21 20:32:32 +00:00
if (fcn) {
/* Rename function */
dialog->setWindowTitle(tr("Rename function %1").arg(fcn->name));
dialog->setName(fcn->name);
2018-03-21 20:32:32 +00:00
if (dialog->exec()) {
QString new_name = dialog->getName();
Core()->renameFunction(fcn->name, new_name);
2017-11-26 16:53:05 +00:00
}
2018-03-21 20:32:32 +00:00
} else if (f) {
/* Rename current flag */
dialog->setWindowTitle(tr("Rename flag %1").arg(f->name));
dialog->setName(f->name);
2018-03-21 20:32:32 +00:00
if (dialog->exec()) {
QString new_name = dialog->getName();
Core()->renameFlag(f->name, new_name);
2017-11-26 16:53:05 +00:00
}
2018-03-21 20:32:32 +00:00
} else {
return;
}
}
2017-11-30 14:16:39 +00:00
void DisassemblyContextMenu::on_actionRenameUsedHere_triggered()
{
2017-11-30 21:18:09 +00:00
QJsonArray array = Core()->cmdj("anj @ " + QString::number(offset)).array();
2018-03-21 20:32:32 +00:00
if (array.isEmpty()) {
2017-11-30 14:16:39 +00:00
return;
}
2017-11-30 21:18:09 +00:00
QJsonObject thingUsedHere = array.first().toObject();
QString type = thingUsedHere.value("type").toString();
2017-11-30 14:16:39 +00:00
RenameDialog *dialog = new RenameDialog(this);
2017-11-30 21:18:09 +00:00
QString oldName;
2018-03-21 20:32:32 +00:00
if (type == "address") {
2017-11-30 21:18:09 +00:00
RVA offset = thingUsedHere["offset"].toVariant().toULongLong();
dialog->setWindowTitle(tr("Add flag at %1").arg(RAddressString(offset)));
dialog->setName("label." + QString::number(offset, 16));
2018-03-21 20:32:32 +00:00
} else {
oldName = thingUsedHere.value("name").toString();
2017-11-30 21:18:09 +00:00
dialog->setWindowTitle(tr("Rename %1").arg(oldName));
dialog->setName(oldName);
}
2018-03-21 20:32:32 +00:00
if (dialog->exec()) {
2017-11-30 21:18:09 +00:00
QString newName = dialog->getName().trimmed();
2018-03-21 20:32:32 +00:00
if (!newName.isEmpty()) {
2017-11-30 21:18:09 +00:00
Core()->cmd("an " + newName + " @ " + QString::number(offset));
2018-03-21 20:32:32 +00:00
if (type == "address" || type == "flag") {
Core()->triggerFlagsChanged();
2018-03-21 20:32:32 +00:00
} else if (type == "var") {
Core()->triggerVarsChanged();
2018-03-21 20:32:32 +00:00
} else if (type == "function") {
Core()->triggerFunctionRenamed(oldName, newName);
}
2017-11-30 21:18:09 +00:00
}
2017-11-30 14:16:39 +00:00
}
}
void DisassemblyContextMenu::on_actionSetFunctionVarTypes_triggered()
{
SetFunctionVarTypes *dialog;
RAnalFunction *fcn = Core()->functionAt(offset);
dialog = new SetFunctionVarTypes(this);
if(fcn)
{
dialog->setWindowTitle(tr("Set Variable Types for Function: %1").arg(fcn->name));
}
dialog->setFcn(fcn);
dialog->exec();
}
void DisassemblyContextMenu::on_actionXRefs_triggered()
{
XrefsDialog *dialog = new XrefsDialog(this);
dialog->fillRefsForAddress(offset, RAddressString(offset), false);
dialog->exec();
}
void DisassemblyContextMenu::on_actionDisplayOptions_triggered()
{
auto *dialog = new PreferencesDialog(this->window());
dialog->showSection(PreferencesDialog::Section::Disassembly);
dialog->show();
}
2018-08-04 18:05:56 +00:00
void DisassemblyContextMenu::on_actionSetToCode_triggered()
{
2018-08-04 18:05:56 +00:00
Core()->setToCode(offset);
}
2018-08-04 18:05:56 +00:00
void DisassemblyContextMenu::on_actionSetToData_triggered()
{
2018-08-04 18:05:56 +00:00
int size = Core()->sizeofDataMeta(offset);
if (size > 8 || (size && (size & (size - 1)))) {
return;
}
if (size == 0 || size == 8) {
size = 1;
} else {
size *= 2;
}
setToData(size);
}
2018-08-04 18:05:56 +00:00
void DisassemblyContextMenu::on_actionSetToDataEx_triggered()
{
2018-08-04 18:05:56 +00:00
auto dialog = new SetToDataDialog(offset, this->window());
if (!dialog->exec()) {
return;
}
setToData(dialog->getItemSize(), dialog->getItemCount());
}
2018-08-04 18:05:56 +00:00
void DisassemblyContextMenu::on_actionDeleteComment_triggered()
{
2018-08-04 18:05:56 +00:00
Core()->delComment(offset);
}
2018-08-04 18:05:56 +00:00
void DisassemblyContextMenu::on_actionDeleteFlag_triggered()
{
2018-08-04 18:05:56 +00:00
Core()->delFlag(offset);
}
2018-08-04 18:05:56 +00:00
void DisassemblyContextMenu::on_actionDeleteFunction_triggered()
{
2018-08-04 18:05:56 +00:00
Core()->delFunction(offset);
}
2018-08-04 18:05:56 +00:00
void DisassemblyContextMenu::setBase(QString base)
{
2018-08-04 18:05:56 +00:00
Core()->setImmediateBase(base, offset);
}
2018-08-04 18:05:56 +00:00
void DisassemblyContextMenu::setBits(int bits)
2018-02-12 09:48:06 +00:00
{
2018-08-04 18:05:56 +00:00
Core()->setCurrentBits(bits, offset);
2018-02-12 09:48:06 +00:00
}
2018-08-04 18:05:56 +00:00
void DisassemblyContextMenu::setToData(int size, int repeat)
2018-02-12 09:48:06 +00:00
{
2018-08-04 18:05:56 +00:00
Core()->setToData(offset, size, repeat);
2018-02-12 09:48:06 +00:00
}
2018-08-04 18:05:56 +00:00
QAction *DisassemblyContextMenu::addAnonymousAction(QString name, const char *slot,
QKeySequence keySequence)
2018-02-12 09:48:06 +00:00
{
2018-08-04 18:05:56 +00:00
auto action = new QAction();
addAction(action);
anonymousActions.append(action);
initAction(action, name, slot, keySequence);
return action;
2018-02-12 09:48:06 +00:00
}
2018-08-04 18:05:56 +00:00
void DisassemblyContextMenu::initAction(QAction *action, QString name, const char *slot)
{
2018-08-04 18:05:56 +00:00
action->setParent(this);
action->setText(name);
if (slot) {
connect(action, SIGNAL(triggered(bool)), this, slot);
}
}
2018-08-04 18:05:56 +00:00
void DisassemblyContextMenu::initAction(QAction *action, QString name,
const char *slot, QKeySequence keySequence)
{
2018-08-04 18:05:56 +00:00
initAction(action, name, slot);
if (keySequence.isEmpty()) {
return;
}
action->setShortcut(keySequence);
auto pWidget = parentWidget();
2018-08-04 18:05:56 +00:00
auto shortcut = new QShortcut(keySequence, pWidget);
shortcut->setContext(Qt::WidgetWithChildrenShortcut);
connect(shortcut, SIGNAL(activated()), this, slot);
}
2018-08-04 18:05:56 +00:00
void DisassemblyContextMenu::initAction(QAction *action, QString name,
const char *slot, QList<QKeySequence> keySequenceList)
{
2018-08-04 18:05:56 +00:00
initAction(action, name, slot);
if (keySequenceList.empty()) {
return;
}
action->setShortcuts(keySequenceList);
auto pWidget = parentWidget();
2018-08-04 18:05:56 +00:00
for (auto keySequence : keySequenceList) {
auto shortcut = new QShortcut(keySequence, pWidget);
shortcut->setContext(Qt::WidgetWithChildrenShortcut);
connect(shortcut, SIGNAL(activated()), this, slot);
}
2018-08-04 18:05:56 +00:00
}