diff --git a/src/core/Cutter.cpp b/src/core/Cutter.cpp index 0f646b810..a5eeed994 100644 --- a/src/core/Cutter.cpp +++ b/src/core/Cutter.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -772,6 +773,7 @@ void CutterCore::editBytesEndian(RVA addr, const QString &bytes) void CutterCore::setToCode(RVA addr) { + qDebug() << "setToCode" << addr << "\n"; CORE_LOCK(); rz_meta_del(core->analysis, RZ_META_TYPE_STRING, core->offset, 1); rz_meta_del(core->analysis, RZ_META_TYPE_DATA, core->offset, 1); @@ -842,6 +844,7 @@ QString CutterCore::getMetaString(RVA addr) void CutterCore::setToData(RVA addr, int size, int repeat) { + qDebug() << "setToData" << addr << size << repeat << "\n"; if (size <= 0 || repeat <= 0) { return; } diff --git a/src/menus/DisassemblyContextMenu.cpp b/src/menus/DisassemblyContextMenu.cpp index fbadfecac..13afce8ad 100644 --- a/src/menus/DisassemblyContextMenu.cpp +++ b/src/menus/DisassemblyContextMenu.cpp @@ -1,4 +1,5 @@ #include "DisassemblyContextMenu.h" +#include "common/DisassemblyPreview.h" #include "dialogs/preferences/PreferencesDialog.h" #include "dialogs/EditInstructionDialog.h" #include "dialogs/CommentsDialog.h" @@ -15,6 +16,8 @@ #include #include #include +#include +#include #include #include #include @@ -242,7 +245,7 @@ void DisassemblyContextMenu::addSetAsMenu() { setAsMenu = addMenu(tr("Set as...")); - initAction(&actionSetToCode, tr("Code"), SLOT(on_actionSetToCode_triggered()), + initAction(&actionSetToCode, tr("Code"), SLOT(applySetToCode()), getSetToCodeSequence()); setAsMenu->addAction(&actionSetToCode); @@ -262,35 +265,83 @@ void DisassemblyContextMenu::addSetAsMenu() addSetToDataMenu(); } +void DisassemblyContextMenu::applySetToCode() { + qDebug() << "Applying set to code" << "\n"; + if (selectedLines.size() > 1) { + QVector> offsets; + for (const auto &selection : selectedLines) { + int startPos = selection.cursor.selectionStart(); + RVA lineOffset = DisassemblyPreview::readDisassemblyOffset(selection.cursor); + offsets.append(qMakePair(startPos, lineOffset)); + } + + // Sorting by start position in descending order + std::sort(offsets.begin(), offsets.end(), + [](const QPair &a, const QPair &b) { + return a.first > b.first; + }); + + for (const auto &offset : offsets) { + qDebug() << "Offset:" << offset.second; + on_actionSetToCode_triggered(offset.second); + } + } else if (selectedLines.size() <= 1) { + on_actionSetToCode_triggered(); + } + selectedLines.clear(); +} + void DisassemblyContextMenu::addSetToDataMenu() { setToDataMenu = setAsMenu->addMenu(tr("Data...")); initAction(&actionSetToDataByte, tr("Byte")); setToDataMenu->addAction(&actionSetToDataByte); - connect(&actionSetToDataByte, &QAction::triggered, this, [this] { setToData(1); }); + connect(&actionSetToDataByte, &QAction::triggered, this, [this] { applySetToData(1); }); initAction(&actionSetToDataWord, tr("Word")); setToDataMenu->addAction(&actionSetToDataWord); - connect(&actionSetToDataWord, &QAction::triggered, this, [this] { setToData(2); }); + connect(&actionSetToDataWord, &QAction::triggered, this, [this] { applySetToData(2); }); initAction(&actionSetToDataDword, tr("Dword")); setToDataMenu->addAction(&actionSetToDataDword); - connect(&actionSetToDataDword, &QAction::triggered, this, [this] { setToData(4); }); + connect(&actionSetToDataDword, &QAction::triggered, this, [this] { applySetToData(4); }); initAction(&actionSetToDataQword, tr("Qword")); setToDataMenu->addAction(&actionSetToDataQword); - connect(&actionSetToDataQword, &QAction::triggered, this, [this] { setToData(8); }); + connect(&actionSetToDataQword, &QAction::triggered, this, [this] { applySetToData(8); }); - initAction(&actionSetToDataEx, "...", SLOT(on_actionSetToDataEx_triggered()), - getSetToDataExSequence()); + initAction(&actionSetToDataEx, "...", SLOT(on_actionSetToDataEx_triggered()), getSetToDataExSequence()); setToDataMenu->addAction(&actionSetToDataEx); +} + +void DisassemblyContextMenu::applySetToData(int dataSize) { + qDebug() << "Applying set to data with size:" << dataSize << "\n"; + if (selectedLines.size() > 1) { + QVector> offsets; + for (const auto &selection : selectedLines) { + int startPos = selection.cursor.selectionStart(); + RVA lineOffset = DisassemblyPreview::readDisassemblyOffset(selection.cursor); + offsets.append(qMakePair(startPos, lineOffset)); + } - auto switchAction = new QAction(this); - initAction(switchAction, "Switch Data", SLOT(on_actionSetToData_triggered()), - getSetToDataSequence()); + // Sorting by start position in descending order + std::sort(offsets.begin(), offsets.end(), + [](const QPair &a, const QPair &b) { + return a.first > b.first; + }); + + for (const auto &offset : offsets) { + qDebug() << "Offset:" << offset.second; + setToData(offset.second, dataSize); + } + } else if (selectedLines.size() <= 1) { + setToData(dataSize); + } + selectedLines.clear(); } + void DisassemblyContextMenu::addEditMenu() { editMenu = addMenu(tr("Edit")); @@ -365,6 +416,27 @@ QVector DisassemblyContextMenu::getThingU return result; } + +void DisassemblyContextMenu::prepareMenu(const QList& selectedLines) { + this->clear(); + this->selectedLines = selectedLines; + + qDebug() << "Number of selected lines:" << selectedLines.size(); + for (const auto& selection : selectedLines) { + int cursorPosition = selection.cursor.position(); + int anchorPosition = selection.cursor.anchor(); + auto offset = DisassemblyPreview::readDisassemblyOffset(selection.cursor); + + qDebug() << "Cursor position:" << cursorPosition << "Anchor position:" << anchorPosition << "Offset:" << offset << "\n"; + } + + addAction(&actionCopy); + + if (selectedLines.size() > 1) { + addSetAsMenu(); + } +} + void DisassemblyContextMenu::setOffset(RVA offset) { this->offset = offset; @@ -964,16 +1036,31 @@ void DisassemblyContextMenu::on_actionSetToCode_triggered() Core()->setToCode(offset); } +void DisassemblyContextMenu::on_actionSetToCode_triggered(RVA offset) +{ + Core()->setToCode(offset); +} + void DisassemblyContextMenu::on_actionSetAsString_triggered() { Core()->setAsString(offset); } +void DisassemblyContextMenu::on_actionSetAsString_triggered(RVA offset) +{ + Core()->setAsString(offset); +} + void DisassemblyContextMenu::on_actionSetAsStringRemove_triggered() { Core()->removeString(offset); } +void DisassemblyContextMenu::on_actionSetAsStringRemove_triggered(RVA offset) +{ + Core()->removeString(offset); +} + void DisassemblyContextMenu::on_actionSetAsStringAdvanced_triggered() { EditStringDialog dialog(parentForDialog()); @@ -1116,6 +1203,11 @@ void DisassemblyContextMenu::setToData(int size, int repeat) Core()->setToData(offset, size, repeat); } +void DisassemblyContextMenu::setToData(RVA offset, int size, int repeat) +{ + Core()->setToData(offset, size, repeat); +} + QAction *DisassemblyContextMenu::addAnonymousAction(QString name, const char *slot, QKeySequence keySequence) { diff --git a/src/menus/DisassemblyContextMenu.h b/src/menus/DisassemblyContextMenu.h index 0cf915561..0842eda9f 100644 --- a/src/menus/DisassemblyContextMenu.h +++ b/src/menus/DisassemblyContextMenu.h @@ -4,6 +4,8 @@ #include "core/Cutter.h" #include "common/IOModesController.h" #include +#include +#include #include class MainWindow; @@ -22,6 +24,8 @@ class CUTTER_EXPORT DisassemblyContextMenu : public QMenu public slots: void setOffset(RVA offset); void setCanCopy(bool enabled); + void prepareMenu(const QList& selectedLines); + /** * @brief Sets the value of curHighlightedWord @@ -61,9 +65,13 @@ private slots: void on_actionContinueUntil_triggered(); void on_actionSetPC_triggered(); + void applySetToCode(); void on_actionSetToCode_triggered(); + void on_actionSetToCode_triggered(RVA offset); void on_actionSetAsString_triggered(); + void on_actionSetAsString_triggered(RVA offset); void on_actionSetAsStringRemove_triggered(); + void on_actionSetAsStringRemove_triggered(RVA offset); void on_actionSetAsStringAdvanced_triggered(); void on_actionSetToData_triggered(); void on_actionSetToDataEx_triggered(); @@ -100,6 +108,7 @@ private slots: bool canCopy; QString curHighlightedWord; // The current highlighted word MainWindow *mainWindow; + QList selectedLines; IOModesController ioModesController; QList anonymousActions; @@ -189,12 +198,13 @@ private slots: void setBase(QString base); void setToData(int size, int repeat = 1); + void setToData(RVA offset, int size, int repeat = 1); void setBits(int bits); - void addSetBaseMenu(); void addSetBitsMenu(); void addSetAsMenu(); void addSetToDataMenu(); + void applySetToData(int datasize); void addEditMenu(); void addAddAtMenu(); void addBreakpointMenu(); diff --git a/src/widgets/DisassemblyWidget.cpp b/src/widgets/DisassemblyWidget.cpp index bbeef00e9..c281aa316 100644 --- a/src/widgets/DisassemblyWidget.cpp +++ b/src/widgets/DisassemblyWidget.cpp @@ -464,6 +464,12 @@ void DisassemblyWidget::highlightMultiLineSelections() void DisassemblyWidget::showDisasContextMenu(const QPoint &pt) { + qDebug() << "showDisasContextMenu()" << "\n"; + auto selectedLines = mDisasTextEdit->getMultiLineSelections(); + if (selectedLines.size() > 1) { + mCtxMenu->prepareMenu(selectedLines); + } + mCtxMenu->exec(mDisasTextEdit->mapToGlobal(pt)); } @@ -843,7 +849,7 @@ void DisassemblyTextEdit::mousePressEvent(QMouseEvent *event) // Format selection QTextEdit::ExtraSelection selection; - selection.format.setBackground(QColor("green")); + selection.format.setBackground(QColor("darkBlue")); selection.format.setProperty(QTextFormat::FullWidthSelection, true); // Move cursor to start of the line @@ -881,6 +887,9 @@ void DisassemblyTextEdit::mousePressEvent(QMouseEvent *event) for (const auto &selection : multilineSelections) { qDebug() << "Start:" << selection.cursor.selectionStart() << "End:" << selection.cursor.selectionEnd(); + qDebug() << selection.cursor.block().text(); + auto offset = DisassemblyPreview::readDisassemblyOffset(selection.cursor); + qDebug() << "Offset:" << offset << "\n"; } }