diff --git a/src/core/Cutter.cpp b/src/core/Cutter.cpp index b3906312..ca115b8e 100644 --- a/src/core/Cutter.cpp +++ b/src/core/Cutter.cpp @@ -565,6 +565,16 @@ void CutterCore::setCurrentBits(int bits, RVA offset) emit instructionChanged(offset); } +void CutterCore::applyStructureOffset(const QString &structureOffset, RVA offset) +{ + if (offset == RVA_INVALID) { + offset = getOffset(); + } + + this->cmdRaw("ta " + structureOffset + " @ " + QString::number(offset)); + emit instructionChanged(offset); +} + void CutterCore::seek(ut64 offset) { // Slower than using the API, but the API is not complete diff --git a/src/core/Cutter.h b/src/core/Cutter.h index 52ecd326..52a97191 100644 --- a/src/core/Cutter.h +++ b/src/core/Cutter.h @@ -106,6 +106,15 @@ public: void setImmediateBase(const QString &r2BaseName, RVA offset = RVA_INVALID); void setCurrentBits(int bits, RVA offset = RVA_INVALID); + /*! + * \brief Changes immediate displacement to structure offset + * This function makes use of the "ta" command of r2 to apply structure + * offset to the immediate displacement used in the given instruction + * \param structureOffset The name of struct which will be applied + * \param offset The address of the instruction where the struct will be applied + */ + void applyStructureOffset(const QString &structureOffset, RVA offset = RVA_INVALID); + /* Classes */ QList getAllAnalClasses(bool sorted); QList getAnalClassMethods(const QString &cls); diff --git a/src/dialogs/EditVariablesDialog.cpp b/src/dialogs/EditVariablesDialog.cpp index 50fe3f5b..945c98d9 100644 --- a/src/dialogs/EditVariablesDialog.cpp +++ b/src/dialogs/EditVariablesDialog.cpp @@ -41,6 +41,9 @@ void EditVariablesDialog::applyFields() if (newName != desc.name) { Core()->cmdRaw(QString("afvn %1 %2").arg(desc.name).arg(newName)); } + + // Refresh the views to reflect the changes to vars + emit Core()->refreshCodeViews(); } void EditVariablesDialog::updateFields() @@ -63,7 +66,7 @@ void EditVariablesDialog::populateTypesComboBox() ui->typeComboBox->addItems(userStructures); ui->typeComboBox->insertSeparator(ui->typeComboBox->count()); - primitiveTypesTypeList = Core()->getAllTypes(); + primitiveTypesTypeList = Core()->getAllPrimitiveTypes(); for (const TypeDescription &thisType : primitiveTypesTypeList) { ui->typeComboBox->addItem(thisType.type); diff --git a/src/menus/DisassemblyContextMenu.cpp b/src/menus/DisassemblyContextMenu.cpp index 270bb89c..e8932fcf 100644 --- a/src/menus/DisassemblyContextMenu.cpp +++ b/src/menus/DisassemblyContextMenu.cpp @@ -71,6 +71,10 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent) addSetBitsMenu(); + structureOffsetMenu = addMenu(tr("Structure offset")); + connect(structureOffsetMenu, SIGNAL(triggered(QAction*)), + this, SLOT(on_actionStructureOffsetMenu_triggered(QAction*))); + initAction(&actionSetToCode, tr("Set as Code"), SLOT(on_actionSetToCode_triggered()), getSetToCodeSequence()); addAction(&actionSetToCode); @@ -245,6 +249,48 @@ void DisassemblyContextMenu::aboutToShowSlot() setBaseMenu->menuAction()->setVisible(immBase); setBitsMenu->menuAction()->setVisible(true); + // Create structure offset menu if it makes sense + QString memBaseReg; // Base register + QVariant memDisp; // Displacement + if (instObject.contains("opex") && instObject["opex"].toObject().contains("operands")) { + // Loop through both the operands of the instruction + for (const QJsonValue value: instObject["opex"].toObject()["operands"].toArray()) { + QJsonObject operand = value.toObject(); + if (operand.contains("type") && operand["type"].toString() == "mem" && + operand.contains("base") && !operand["base"].toString().contains("bp") && + operand.contains("disp") && operand["disp"].toVariant().toLongLong() > 0) { + + // The current operand is the one which has an immediate displacement + memBaseReg = operand["base"].toString(); + memDisp = operand["disp"].toVariant(); + break; + + } + } + } + if (memBaseReg.isEmpty()) { + // hide structure offset menu + structureOffsetMenu->menuAction()->setVisible(false); + } else { + // show structure offset menu + structureOffsetMenu->menuAction()->setVisible(true); + structureOffsetMenu->clear(); + + // Get the possible offsets using the "tas" command + // TODO: add tasj command to radare2 and then use it here + QString ret = Core()->cmd("tas " + memDisp.toString()); + for (QString val: ret.split("\n")) { + if (val.isEmpty()) { + continue; + } + structureOffsetMenu->addAction("[" + memBaseReg + " + " + val + "]")->setData(val); + } + if (structureOffsetMenu->isEmpty()) { + // No possible offset was found so hide the menu + structureOffsetMenu->menuAction()->setVisible(false); + } + } + actionAnalyzeFunction.setVisible(true); QString comment = Core()->cmd("CC." + RAddressString(offset)); @@ -699,6 +745,11 @@ void DisassemblyContextMenu::on_actionSetToDataEx_triggered() setToData(dialog->getItemSize(), dialog->getItemCount()); } +void DisassemblyContextMenu::on_actionStructureOffsetMenu_triggered(QAction *action) +{ + Core()->applyStructureOffset(action->data().toString(), offset); +} + void DisassemblyContextMenu::on_actionDeleteComment_triggered() { Core()->delComment(offset); diff --git a/src/menus/DisassemblyContextMenu.h b/src/menus/DisassemblyContextMenu.h index e6f18d0f..96b9d7a6 100644 --- a/src/menus/DisassemblyContextMenu.h +++ b/src/menus/DisassemblyContextMenu.h @@ -55,6 +55,14 @@ private slots: void on_actionSetToData_triggered(); void on_actionSetToDataEx_triggered(); + /*! + * \brief Executed on selecting an offset from the structureOffsetMenu + * Uses the applyStructureOffset() function of CutterCore to apply the + * structure offset + * \param action The action which trigered the event + */ + void on_actionStructureOffsetMenu_triggered(QAction *action); + private: QKeySequence getCopySequence() const; QKeySequence getCommentSequence() const; @@ -100,6 +108,8 @@ private: QAction actionDeleteFlag; QAction actionDeleteFunction; + QMenu *structureOffsetMenu; + QMenu *setBaseMenu; QAction actionSetBaseBinary; QAction actionSetBaseOctal;