2017-10-10 10:17:05 +00:00
|
|
|
#include "DisassemblyContextMenu.h"
|
2017-12-14 13:42:24 +00:00
|
|
|
#include "dialogs/preferences/PreferencesDialog.h"
|
2018-02-12 20:12:13 +00:00
|
|
|
#include "dialogs/EditInstructionDialog.h"
|
2017-10-10 10:17:05 +00:00
|
|
|
#include "dialogs/CommentsDialog.h"
|
|
|
|
#include "dialogs/FlagDialog.h"
|
|
|
|
#include "dialogs/RenameDialog.h"
|
|
|
|
#include "dialogs/XrefsDialog.h"
|
|
|
|
#include <QtCore>
|
2017-11-03 11:31:20 +00:00
|
|
|
#include <QShortcut>
|
2018-02-12 20:12:13 +00:00
|
|
|
#include <QJsonArray>
|
2017-10-10 10:17:05 +00:00
|
|
|
|
2017-11-19 17:49:29 +00:00
|
|
|
DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent)
|
|
|
|
: QMenu(parent),
|
|
|
|
offset(0),
|
2017-12-02 15:43:21 +00:00
|
|
|
canCopy(false),
|
2018-02-12 20:12:13 +00:00
|
|
|
actionEditInstruction(this),
|
2018-03-10 07:27:09 +00:00
|
|
|
actionNopInstruction(this),
|
|
|
|
actionJmpReverse(this),
|
2018-02-12 20:12:13 +00:00
|
|
|
actionEditBytes(this),
|
2017-12-02 15:43:21 +00:00
|
|
|
actionCopy(this),
|
2017-11-19 17:49:29 +00:00
|
|
|
actionAddComment(this),
|
|
|
|
actionAddFlag(this),
|
2017-12-10 20:40:15 +00:00
|
|
|
actionCreateFunction(this),
|
2017-11-19 17:49:29 +00:00
|
|
|
actionRename(this),
|
2017-11-30 14:16:39 +00:00
|
|
|
actionRenameUsedHere(this),
|
2017-11-19 17:49:29 +00:00
|
|
|
actionXRefs(this),
|
2017-12-14 19:51:24 +00:00
|
|
|
actionDisplayOptions(this),
|
2017-12-11 19:16:47 +00:00
|
|
|
actionDeleteComment(this),
|
|
|
|
actionDeleteFlag(this),
|
|
|
|
actionDeleteFunction(this),
|
2017-11-28 13:13:22 +00:00
|
|
|
actionSetBaseBinary(this),
|
|
|
|
actionSetBaseOctal(this),
|
|
|
|
actionSetBaseDecimal(this),
|
|
|
|
actionSetBaseHexadecimal(this),
|
|
|
|
actionSetBasePort(this),
|
|
|
|
actionSetBaseIPAddr(this),
|
|
|
|
actionSetBaseSyscall(this),
|
2018-02-12 09:48:06 +00:00
|
|
|
actionSetBaseString(this),
|
|
|
|
actionSetBits16(this),
|
|
|
|
actionSetBits32(this),
|
|
|
|
actionSetBits64(this)
|
2017-10-10 10:17:05 +00:00
|
|
|
{
|
2017-12-10 20:40:15 +00:00
|
|
|
createAction(&actionCopy, tr("Copy"), getCopySequence(), SLOT(on_actionCopy_triggered()));
|
2017-12-02 15:43:21 +00:00
|
|
|
copySeparator = addSeparator();
|
2018-03-21 20:32:32 +00:00
|
|
|
createAction(&actionAddComment, tr("Add Comment"), getCommentSequence(),
|
|
|
|
SLOT(on_actionAddComment_triggered()));
|
|
|
|
createAction(&actionAddFlag, tr("Add Flag"), getAddFlagSequence(),
|
|
|
|
SLOT(on_actionAddFlag_triggered()));
|
|
|
|
createAction(&actionCreateFunction, tr("Create Function"), {}, SLOT(
|
|
|
|
on_actionCreateFunction_triggered()));
|
2017-12-10 20:40:15 +00:00
|
|
|
createAction(&actionRename, tr("Rename"), getRenameSequence(), SLOT(on_actionRename_triggered()));
|
2018-03-21 20:32:32 +00:00
|
|
|
createAction(&actionRenameUsedHere, "Rename Flag/Fcn/Var Used Here", getRenameUsedHereSequence(),
|
|
|
|
SLOT(on_actionRenameUsedHere_triggered()));
|
2017-11-03 11:31:20 +00:00
|
|
|
|
2018-03-21 20:32:32 +00:00
|
|
|
createAction(&actionDeleteComment, tr("Delete comment"), {}, SLOT(
|
|
|
|
on_actionDeleteComment_triggered()));
|
2017-12-11 13:07:12 +00:00
|
|
|
createAction(&actionDeleteFlag, tr("Delete flag"), {}, SLOT(on_actionDeleteFlag_triggered()));
|
2018-03-21 20:32:32 +00:00
|
|
|
createAction(&actionDeleteFunction, tr("Undefine function"), {}, SLOT(
|
|
|
|
on_actionDeleteFunction_triggered()));
|
2017-12-11 13:07:12 +00:00
|
|
|
|
2017-11-28 13:50:41 +00:00
|
|
|
setBaseMenu = new QMenu(tr("Set Immediate Base to..."), this);
|
|
|
|
setBaseMenuAction = addMenu(setBaseMenu);
|
2017-11-28 13:13:22 +00:00
|
|
|
actionSetBaseBinary.setText(tr("Binary"));
|
2017-11-28 13:50:41 +00:00
|
|
|
setBaseMenu->addAction(&actionSetBaseBinary);
|
2017-11-28 13:13:22 +00:00
|
|
|
actionSetBaseOctal.setText(tr("Octal"));
|
2017-11-28 13:50:41 +00:00
|
|
|
setBaseMenu->addAction(&actionSetBaseOctal);
|
2017-11-28 13:13:22 +00:00
|
|
|
actionSetBaseDecimal.setText(tr("Decimal"));
|
2017-11-28 13:50:41 +00:00
|
|
|
setBaseMenu->addAction(&actionSetBaseDecimal);
|
2017-11-28 13:13:22 +00:00
|
|
|
actionSetBaseHexadecimal.setText(tr("Hexadecimal"));
|
2017-11-28 13:50:41 +00:00
|
|
|
setBaseMenu->addAction(&actionSetBaseHexadecimal);
|
2017-11-28 13:13:22 +00:00
|
|
|
actionSetBasePort.setText(tr("Network Port"));
|
2017-11-28 13:50:41 +00:00
|
|
|
setBaseMenu->addAction(&actionSetBasePort);
|
2017-11-28 13:13:22 +00:00
|
|
|
actionSetBaseIPAddr.setText(tr("IP Address"));
|
2017-11-28 13:50:41 +00:00
|
|
|
setBaseMenu->addAction(&actionSetBaseIPAddr);
|
2017-11-28 13:13:22 +00:00
|
|
|
actionSetBaseSyscall.setText(tr("Syscall"));
|
2017-11-28 13:50:41 +00:00
|
|
|
setBaseMenu->addAction(&actionSetBaseSyscall);
|
2017-11-28 13:13:22 +00:00
|
|
|
actionSetBaseString.setText(tr("String"));
|
2017-11-28 13:50:41 +00:00
|
|
|
setBaseMenu->addAction(&actionSetBaseString);
|
2018-02-12 09:48:06 +00:00
|
|
|
|
|
|
|
setBitsMenu = new QMenu(tr("Set current bits to..."), this);
|
|
|
|
setBitsMenuAction = addMenu(setBitsMenu);
|
|
|
|
actionSetBits16.setText("16");
|
|
|
|
setBitsMenu->addAction(&actionSetBits16);
|
|
|
|
actionSetBits32.setText("32");
|
|
|
|
setBitsMenu->addAction(&actionSetBits32);
|
|
|
|
actionSetBits64.setText("64");
|
|
|
|
setBitsMenu->addAction(&actionSetBits64);
|
|
|
|
|
2017-12-10 20:40:15 +00:00
|
|
|
addSeparator();
|
|
|
|
createAction(&actionXRefs, tr("Show X-Refs"), getXRefSequence(), SLOT(on_actionXRefs_triggered()));
|
2018-03-21 20:32:32 +00:00
|
|
|
createAction(&actionDisplayOptions, tr("Show Options"), getDisplayOptionsSequence(),
|
|
|
|
SLOT(on_actionDisplayOptions_triggered()));
|
2017-11-28 13:13:22 +00:00
|
|
|
|
2018-02-12 20:12:13 +00:00
|
|
|
addSeparator();
|
|
|
|
editMenu = new QMenu(tr("Edit"), this);
|
|
|
|
editMenuAction = addMenu(editMenu);
|
|
|
|
actionEditInstruction.setText(tr("Instruction"));
|
|
|
|
editMenu->addAction(&actionEditInstruction);
|
2018-03-05 14:20:55 +00:00
|
|
|
actionNopInstruction.setText(tr("Nop Instruction"));
|
|
|
|
editMenu->addAction(&actionNopInstruction);
|
2018-02-12 20:12:13 +00:00
|
|
|
actionEditBytes.setText(tr("Bytes"));
|
|
|
|
editMenu->addAction(&actionEditBytes);
|
2018-03-10 07:27:09 +00:00
|
|
|
actionJmpReverse.setText(tr("Reverse Jump"));
|
|
|
|
editMenu->addAction(&actionJmpReverse);
|
2018-02-12 20:12:13 +00:00
|
|
|
|
2018-03-21 20:32:32 +00:00
|
|
|
connect(&actionEditInstruction, SIGNAL(triggered(bool)), this,
|
|
|
|
SLOT(on_actionEditInstruction_triggered()));
|
|
|
|
connect(&actionNopInstruction, SIGNAL(triggered(bool)), this,
|
|
|
|
SLOT(on_actionNopInstruction_triggered()));
|
2018-02-12 20:12:13 +00:00
|
|
|
connect(&actionEditBytes, SIGNAL(triggered(bool)), this, SLOT(on_actionEditBytes_triggered()));
|
2018-03-10 07:27:09 +00:00
|
|
|
connect(&actionJmpReverse, SIGNAL(triggered(bool)), this, SLOT(on_actionJmpReverse_triggered()));
|
2018-02-12 20:12:13 +00:00
|
|
|
|
2018-03-21 20:32:32 +00:00
|
|
|
connect(&actionSetBaseBinary, SIGNAL(triggered(bool)), this,
|
|
|
|
SLOT(on_actionSetBaseBinary_triggered()));
|
|
|
|
connect(&actionSetBaseOctal, SIGNAL(triggered(bool)), this,
|
|
|
|
SLOT(on_actionSetBaseOctal_triggered()));
|
|
|
|
connect(&actionSetBaseDecimal, SIGNAL(triggered(bool)), this,
|
|
|
|
SLOT(on_actionSetBaseDecimal_triggered()));
|
|
|
|
connect(&actionSetBaseHexadecimal, SIGNAL(triggered(bool)), this,
|
|
|
|
SLOT(on_actionSetBaseHexadecimal_triggered()));
|
2017-11-28 13:13:22 +00:00
|
|
|
connect(&actionSetBasePort, SIGNAL(triggered(bool)), this, SLOT(on_actionSetBasePort_triggered()));
|
2018-03-21 20:32:32 +00:00
|
|
|
connect(&actionSetBaseIPAddr, SIGNAL(triggered(bool)), this,
|
|
|
|
SLOT(on_actionSetBaseIPAddr_triggered()));
|
|
|
|
connect(&actionSetBaseSyscall, SIGNAL(triggered(bool)), this,
|
|
|
|
SLOT(on_actionSetBaseSyscall_triggered()));
|
|
|
|
connect(&actionSetBaseString, SIGNAL(triggered(bool)), this,
|
|
|
|
SLOT(on_actionSetBaseString_triggered()));
|
2017-11-28 13:50:41 +00:00
|
|
|
|
2018-02-12 09:48:06 +00:00
|
|
|
connect(&actionSetBits16, SIGNAL(triggered(bool)), this, SLOT(on_actionSetBits16_triggered()));
|
|
|
|
connect(&actionSetBits32, SIGNAL(triggered(bool)), this, SLOT(on_actionSetBits32_triggered()));
|
|
|
|
connect(&actionSetBits64, SIGNAL(triggered(bool)), this, SLOT(on_actionSetBits64_triggered()));
|
|
|
|
|
2017-11-28 13:50:41 +00:00
|
|
|
connect(this, SIGNAL(aboutToShow()), this, SLOT(aboutToShowSlot()));
|
|
|
|
}
|
|
|
|
|
2017-12-10 20:40:15 +00:00
|
|
|
DisassemblyContextMenu::~DisassemblyContextMenu()
|
|
|
|
{
|
2018-03-21 20:32:32 +00:00
|
|
|
for (QAction *action : anonymousActions) {
|
2017-12-10 20:40:15 +00:00
|
|
|
delete action;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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");
|
|
|
|
setBaseMenuAction->setVisible(immBase);
|
2018-02-12 09:48:06 +00:00
|
|
|
setBitsMenuAction->setVisible(true);
|
2017-12-01 10:46:13 +00:00
|
|
|
|
2017-12-11 13:07:12 +00:00
|
|
|
actionCreateFunction.setVisible(true);
|
|
|
|
|
2017-12-10 18:13:37 +00:00
|
|
|
QString comment = Core()->cmd("CC." + RAddressString(offset));
|
2018-03-21 20:32:32 +00:00
|
|
|
if (comment.isNull() || comment.isEmpty()) {
|
2017-12-11 13:07:12 +00:00
|
|
|
actionDeleteComment.setVisible(false);
|
2017-12-01 10:46:13 +00:00
|
|
|
actionAddComment.setText(tr("Add Comment"));
|
2018-03-21 20:32:32 +00:00
|
|
|
} else {
|
2017-12-11 13:07:12 +00:00
|
|
|
actionDeleteComment.setVisible(true);
|
2017-12-01 10:46:13 +00:00
|
|
|
actionAddComment.setText(tr("Edit Comment"));
|
|
|
|
}
|
2017-12-02 15:43:21 +00:00
|
|
|
|
|
|
|
actionCopy.setVisible(canCopy);
|
|
|
|
copySeparator->setVisible(canCopy);
|
2017-12-03 20:23:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
RCore *core = Core()->core();
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_at (core->anal, offset, R_ANAL_FCN_TYPE_NULL);
|
|
|
|
RFlagItem *f = r_flag_get_i (core->flags, offset);
|
2017-12-11 13:07:12 +00:00
|
|
|
|
|
|
|
actionDeleteFlag.setVisible(f ? true : false);
|
|
|
|
actionDeleteFunction.setVisible(fcn ? true : false);
|
|
|
|
|
2018-03-21 20:32:32 +00:00
|
|
|
if (fcn) {
|
2017-12-10 20:40:15 +00:00
|
|
|
actionCreateFunction.setVisible(false);
|
2017-12-03 20:23:02 +00:00
|
|
|
actionRename.setVisible(true);
|
|
|
|
actionRename.setText(tr("Rename function \"%1\"").arg(fcn->name));
|
2018-03-21 20:32:32 +00:00
|
|
|
} else if (f) {
|
2017-12-03 20:23:02 +00:00
|
|
|
actionRename.setVisible(true);
|
|
|
|
actionRename.setText(tr("Rename flag \"%1\"").arg(f->name));
|
2018-03-21 20:32:32 +00:00
|
|
|
} else {
|
2017-12-03 20:23:02 +00:00
|
|
|
actionRename.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);
|
|
|
|
}
|
2018-03-10 07:27:09 +00:00
|
|
|
|
|
|
|
// decide to show Reverse jmp option
|
|
|
|
showReverseJmpQuery();
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
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};
|
|
|
|
}
|
|
|
|
|
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
|
2017-10-10 10:17:05 +00:00
|
|
|
}
|
|
|
|
|
2018-02-12 20:12:13 +00:00
|
|
|
void DisassemblyContextMenu::on_actionEditInstruction_triggered()
|
|
|
|
{
|
|
|
|
EditInstructionDialog *e = new EditInstructionDialog(this);
|
|
|
|
e->setWindowTitle(tr("Edit Instruction at %1").arg(RAddressString(offset)));
|
|
|
|
|
|
|
|
QString oldInstruction = Core()->cmdj("aoj").array().first().toObject()["opcode"].toString();
|
|
|
|
e->setInstruction(oldInstruction);
|
|
|
|
|
2018-03-21 20:32:32 +00:00
|
|
|
if (e->exec()) {}
|
2018-02-12 20:12:13 +00:00
|
|
|
{
|
|
|
|
QString instruction = e->getInstruction();
|
2018-03-21 20:32:32 +00:00
|
|
|
if (instruction != oldInstruction) {
|
2018-02-12 20:12:13 +00:00
|
|
|
Core()->editInstruction(offset, instruction);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-05 14:20:55 +00:00
|
|
|
void DisassemblyContextMenu::on_actionNopInstruction_triggered()
|
|
|
|
{
|
|
|
|
Core()->nopInstruction(offset);
|
|
|
|
}
|
|
|
|
|
2018-03-10 07:27:09 +00:00
|
|
|
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()) {
|
2018-03-10 07:27:09 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
type = array.first().toObject()["type"].toString();
|
2018-03-21 20:32:32 +00:00
|
|
|
if (type == "cjmp") {
|
2018-03-10 07:27:09 +00:00
|
|
|
actionJmpReverse.setVisible(true);
|
2018-03-21 20:32:32 +00:00
|
|
|
} else {
|
2018-03-10 07:27:09 +00:00
|
|
|
actionJmpReverse.setVisible(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DisassemblyContextMenu::on_actionJmpReverse_triggered()
|
|
|
|
{
|
|
|
|
Core()->jmpReverse(offset);
|
|
|
|
}
|
|
|
|
|
2018-02-12 20:12:13 +00:00
|
|
|
void DisassemblyContextMenu::on_actionEditBytes_triggered()
|
|
|
|
{
|
|
|
|
EditInstructionDialog *e = new EditInstructionDialog(this);
|
|
|
|
e->setWindowTitle(tr("Edit Bytes at %1").arg(RAddressString(offset)));
|
|
|
|
|
|
|
|
QString oldBytes = Core()->cmdj("aoj").array().first().toObject()["bytes"].toString();
|
|
|
|
e->setInstruction(oldBytes);
|
|
|
|
|
2018-03-21 20:32:32 +00:00
|
|
|
if (e->exec()) {}
|
2018-02-12 20:12:13 +00:00
|
|
|
{
|
|
|
|
QString bytes = e->getInstruction();
|
2018-03-21 20:32:32 +00:00
|
|
|
if (bytes != oldBytes) {
|
2018-02-12 20:12:13 +00:00
|
|
|
Core()->editBytes(offset, bytes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-02 15:43:21 +00:00
|
|
|
void DisassemblyContextMenu::on_actionCopy_triggered()
|
|
|
|
{
|
|
|
|
emit copy();
|
|
|
|
}
|
|
|
|
|
2017-10-10 10:17:05 +00:00
|
|
|
void DisassemblyContextMenu::on_actionAddComment_triggered()
|
|
|
|
{
|
2017-12-10 18:13:37 +00:00
|
|
|
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);
|
2017-10-10 10:17:05 +00:00
|
|
|
CommentsDialog *c = new CommentsDialog(this);
|
2017-12-01 10:46:13 +00:00
|
|
|
|
2018-03-21 20:32:32 +00:00
|
|
|
if (oldComment.isNull() || oldComment.isEmpty()) {
|
2017-12-01 10:46:13 +00:00
|
|
|
c->setWindowTitle(tr("Add Comment at %1").arg(RAddressString(offset)));
|
2018-03-21 20:32:32 +00:00
|
|
|
} else {
|
2017-12-01 10:46:13 +00:00
|
|
|
c->setWindowTitle(tr("Edit Comment at %1").arg(RAddressString(offset)));
|
|
|
|
}
|
|
|
|
|
|
|
|
c->setComment(oldComment);
|
2018-03-21 20:32:32 +00:00
|
|
|
if (c->exec()) {
|
2017-10-10 10:17:05 +00:00
|
|
|
QString comment = c->getComment();
|
2018-03-21 20:32:32 +00:00
|
|
|
if (comment.isEmpty()) {
|
2017-12-01 10:46:13 +00:00
|
|
|
Core()->delComment(offset);
|
2018-03-21 20:32:32 +00:00
|
|
|
} else {
|
2017-12-01 10:46:13 +00:00
|
|
|
Core()->setComment(offset, comment);
|
|
|
|
}
|
2017-10-10 10:17:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-10 20:40:15 +00:00
|
|
|
void DisassemblyContextMenu::on_actionCreateFunction_triggered()
|
|
|
|
{
|
|
|
|
RenameDialog *dialog = new RenameDialog(this);
|
|
|
|
dialog->setWindowTitle(tr("Add function at %1").arg(RAddressString(offset)));
|
2018-03-21 20:32:32 +00:00
|
|
|
if (dialog->exec()) {
|
2017-12-10 20:40:15 +00:00
|
|
|
QString function_name = dialog->getName();
|
|
|
|
Core()->createFunctionAt(offset, function_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-10 10:17:05 +00:00
|
|
|
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();
|
2017-11-08 09:02:39 +00:00
|
|
|
|
2017-10-10 10:17:05 +00:00
|
|
|
RenameDialog *dialog = new RenameDialog(this);
|
2017-11-26 16:53:05 +00:00
|
|
|
|
2017-12-03 20:23:02 +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) {
|
2017-12-03 20:23:02 +00:00
|
|
|
/* 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()) {
|
2017-12-03 20:23:02 +00:00
|
|
|
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) {
|
2017-12-03 20:23:02 +00:00
|
|
|
/* 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()) {
|
2017-12-03 20:23:02 +00:00
|
|
|
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 {
|
2017-12-03 20:23:02 +00:00
|
|
|
return;
|
|
|
|
}
|
2017-10-10 10:17:05 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2017-11-30 21:30:51 +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 {
|
2017-11-30 21:30:51 +00:00
|
|
|
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));
|
2017-11-30 21:30:51 +00:00
|
|
|
|
2018-03-21 20:32:32 +00:00
|
|
|
if (type == "address" || type == "flag") {
|
2017-11-30 21:30:51 +00:00
|
|
|
Core()->triggerFlagsChanged();
|
2018-03-21 20:32:32 +00:00
|
|
|
} else if (type == "var") {
|
2017-11-30 21:30:51 +00:00
|
|
|
Core()->triggerVarsChanged();
|
2018-03-21 20:32:32 +00:00
|
|
|
} else if (type == "function") {
|
2017-11-30 21:30:51 +00:00
|
|
|
Core()->triggerFunctionRenamed(oldName, newName);
|
|
|
|
}
|
2017-11-30 21:18:09 +00:00
|
|
|
}
|
2017-11-30 14:16:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-10 10:17:05 +00:00
|
|
|
void DisassemblyContextMenu::on_actionXRefs_triggered()
|
|
|
|
{
|
|
|
|
XrefsDialog *dialog = new XrefsDialog(this);
|
|
|
|
dialog->fillRefsForAddress(offset, RAddressString(offset), false);
|
|
|
|
dialog->exec();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DisassemblyContextMenu::on_actionDisplayOptions_triggered()
|
|
|
|
{
|
2017-12-14 13:42:24 +00:00
|
|
|
auto *dialog = new PreferencesDialog(this->window());
|
|
|
|
dialog->showSection(PreferencesDialog::Section::Disassembly);
|
2017-10-10 10:17:05 +00:00
|
|
|
dialog->show();
|
|
|
|
}
|
2017-11-28 13:13:22 +00:00
|
|
|
|
2017-12-11 13:07:12 +00:00
|
|
|
void DisassemblyContextMenu::on_actionDeleteComment_triggered()
|
|
|
|
{
|
|
|
|
Core()->delComment(offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DisassemblyContextMenu::on_actionDeleteFlag_triggered()
|
|
|
|
{
|
|
|
|
Core()->delFlag(offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DisassemblyContextMenu::on_actionDeleteFunction_triggered()
|
|
|
|
{
|
|
|
|
Core()->delFunction(offset);
|
|
|
|
}
|
|
|
|
|
2017-11-28 13:13:22 +00:00
|
|
|
void DisassemblyContextMenu::on_actionSetBaseBinary_triggered()
|
|
|
|
{
|
|
|
|
Core()->setImmediateBase("b", offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DisassemblyContextMenu::on_actionSetBaseOctal_triggered()
|
|
|
|
{
|
|
|
|
Core()->setImmediateBase("o", offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DisassemblyContextMenu::on_actionSetBaseDecimal_triggered()
|
|
|
|
{
|
|
|
|
Core()->setImmediateBase("d", offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DisassemblyContextMenu::on_actionSetBaseHexadecimal_triggered()
|
|
|
|
{
|
|
|
|
Core()->setImmediateBase("h", offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DisassemblyContextMenu::on_actionSetBasePort_triggered()
|
|
|
|
{
|
|
|
|
Core()->setImmediateBase("p", offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DisassemblyContextMenu::on_actionSetBaseIPAddr_triggered()
|
|
|
|
{
|
|
|
|
Core()->setImmediateBase("i", offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DisassemblyContextMenu::on_actionSetBaseSyscall_triggered()
|
|
|
|
{
|
|
|
|
Core()->setImmediateBase("S", offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DisassemblyContextMenu::on_actionSetBaseString_triggered()
|
|
|
|
{
|
|
|
|
Core()->setImmediateBase("s", offset);
|
|
|
|
}
|
2017-12-10 20:40:15 +00:00
|
|
|
|
2018-02-12 09:48:06 +00:00
|
|
|
void DisassemblyContextMenu::on_actionSetBits16_triggered()
|
|
|
|
{
|
|
|
|
Core()->setCurrentBits(16, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DisassemblyContextMenu::on_actionSetBits32_triggered()
|
|
|
|
{
|
|
|
|
Core()->setCurrentBits(32, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DisassemblyContextMenu::on_actionSetBits64_triggered()
|
|
|
|
{
|
|
|
|
Core()->setCurrentBits(64, offset);
|
|
|
|
}
|
|
|
|
|
2017-12-10 20:40:15 +00:00
|
|
|
void DisassemblyContextMenu::createAction(QString name, QKeySequence keySequence, const char *slot)
|
|
|
|
{
|
|
|
|
QAction *action = new QAction(this);
|
|
|
|
anonymousActions.append(action);
|
|
|
|
createAction(action, name, keySequence, slot);
|
|
|
|
}
|
|
|
|
|
2018-03-21 20:32:32 +00:00
|
|
|
void DisassemblyContextMenu::createAction(QAction *action, QString name, QKeySequence keySequence,
|
|
|
|
const char *slot)
|
2017-12-10 20:40:15 +00:00
|
|
|
{
|
|
|
|
action->setText(name);
|
|
|
|
addAction(action);
|
|
|
|
action->setShortcut(keySequence);
|
|
|
|
|
|
|
|
connect(action, SIGNAL(triggered(bool)), this, slot);
|
|
|
|
|
|
|
|
auto pWidget = parentWidget();
|
|
|
|
QShortcut *shortcut = new QShortcut(keySequence, pWidget);
|
|
|
|
shortcut->setContext(Qt::WidgetWithChildrenShortcut);
|
|
|
|
connect(shortcut, SIGNAL(activated()), this, slot);
|
|
|
|
}
|