diff --git a/src/Cutter.cpp b/src/Cutter.cpp index 0ea9967d..b89bc91b 100644 --- a/src/Cutter.cpp +++ b/src/Cutter.cpp @@ -856,6 +856,29 @@ QList CutterCore::getRegisterRefs() return ret; } +QList CutterCore::getVariables(RVA at) +{ + QList ret; + QJsonObject varsObject = cmdj(QString("afvj @ %1").arg(at)).object(); + + auto addVars = [&](VariableDescription::RefType refType, const QJsonArray &array) { + for (const QJsonValue &varValue : array) { + QJsonObject varObject = varValue.toObject(); + VariableDescription desc; + desc.refType = refType; + desc.name = varObject["name"].toString(); + desc.type = varObject["type"].toString(); + ret << desc; + } + }; + + addVars(VariableDescription::RefType::SP, varsObject["sp"].toArray()); + addVars(VariableDescription::RefType::BP, varsObject["bp"].toArray()); + addVars(VariableDescription::RefType::Reg, varsObject["reg"].toArray()); + + return ret; +} + QJsonObject CutterCore::getRegisterJson() { QJsonArray registerRefArray = cmdj("drrj").array(); diff --git a/src/Cutter.h b/src/Cutter.h index 33aeb770..e518ddb5 100644 --- a/src/Cutter.h +++ b/src/Cutter.h @@ -332,6 +332,13 @@ struct RegisterRefDescription { QString ref; }; +struct VariableDescription { + enum class RefType { SP, BP, Reg }; + RefType refType; + QString name; + QString type; +}; + Q_DECLARE_METATYPE(FunctionDescription) Q_DECLARE_METATYPE(ImportDescription) Q_DECLARE_METATYPE(ExportDescription) @@ -365,6 +372,7 @@ Q_DECLARE_METATYPE(MemoryMapDescription) Q_DECLARE_METATYPE(BreakpointDescription) Q_DECLARE_METATYPE(ProcessDescription) Q_DECLARE_METATYPE(RegisterRefDescription) +Q_DECLARE_METATYPE(VariableDescription) class CutterCore: public QObject { @@ -604,6 +612,7 @@ public: QList getAllProcesses(); QList getRegisterRefs(); QJsonObject getRegisterJson(); + QList getVariables(RVA at); QList getXRefs(RVA addr, bool to, bool whole_function, const QString &filterType = QString::null); diff --git a/src/Cutter.pro b/src/Cutter.pro index 54f4f727..e334145a 100644 --- a/src/Cutter.pro +++ b/src/Cutter.pro @@ -214,7 +214,7 @@ SOURCES += \ dialogs/AttachProcDialog.cpp \ widgets/RegisterRefsWidget.cpp \ dialogs/SetToDataDialog.cpp \ - dialogs/SetFunctionVarTypes.cpp \ + dialogs/EditVariablesDialog.cpp \ widgets/ColorSchemePrefWidget.cpp \ common/ColorSchemeFileSaver.cpp \ dialogs/EditFunctionDialog.cpp \ @@ -318,7 +318,7 @@ HEADERS += \ widgets/RegisterRefsWidget.h \ dialogs/SetToDataDialog.h \ common/InitialOptions.h \ - dialogs/SetFunctionVarTypes.h \ + dialogs/EditVariablesDialog.h \ common/ColorSchemeFileSaver.h \ widgets/ColorSchemePrefWidget.h \ dialogs/EditFunctionDialog.h \ @@ -380,7 +380,7 @@ FORMS += \ dialogs/AttachProcDialog.ui \ widgets/RegisterRefsWidget.ui \ dialogs/SetToDataDialog.ui \ - dialogs/SetFunctionVarTypes.ui \ + dialogs/EditVariablesDialog.ui \ widgets/ColorSchemePrefWidget.ui \ widgets/CutterTreeView.ui \ widgets/ComboQuickFilterView.ui \ diff --git a/src/dialogs/EditVariablesDialog.cpp b/src/dialogs/EditVariablesDialog.cpp new file mode 100644 index 00000000..50fe3f5b --- /dev/null +++ b/src/dialogs/EditVariablesDialog.cpp @@ -0,0 +1,76 @@ +#include "EditVariablesDialog.h" +#include "ui_EditVariablesDialog.h" + +#include +#include +#include + + +EditVariablesDialog::EditVariablesDialog(RVA offset, QWidget *parent) : + QDialog(parent), + ui(new Ui::EditVariablesDialog) +{ + ui->setupUi(this); + connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(applyFields())); + connect(ui->dropdownLocalVars, SIGNAL(currentIndexChanged(int)), SLOT(updateFields())); + + QString fcnName = Core()->cmd(QString("afn @ %1").arg(offset)).trimmed(); + setWindowTitle(tr("Set Variable Types for Function: %1").arg(fcnName)); + + variables = Core()->getVariables(offset); + for (const VariableDescription &var : variables) { + ui->dropdownLocalVars->addItem(var.name, QVariant::fromValue(var)); + } + + populateTypesComboBox(); + updateFields(); +} + +EditVariablesDialog::~EditVariablesDialog() +{ + delete ui; +} + +void EditVariablesDialog::applyFields() +{ + VariableDescription desc = ui->dropdownLocalVars->currentData().value(); + + Core()->cmdRaw(QString("afvt %1 %2").arg(desc.name).arg(ui->typeComboBox->currentText())); + + QString newName = ui->dropdownLocalVars->currentText().replace(" ", "_"); + if (newName != desc.name) { + Core()->cmdRaw(QString("afvn %1 %2").arg(desc.name).arg(newName)); + } +} + +void EditVariablesDialog::updateFields() +{ + VariableDescription desc = ui->dropdownLocalVars->currentData().value(); + ui->nameEdit->setText(desc.name); + ui->typeComboBox->setCurrentText(desc.type); +} + + +void EditVariablesDialog::populateTypesComboBox() +{ + //gets all loaded types, structures and enums and puts them in a list + + QStringList userStructures; + QStringList userEnumerations; + QList primitiveTypesTypeList; + + userStructures = Core()->cmdList("ts"); + ui->typeComboBox->addItems(userStructures); + ui->typeComboBox->insertSeparator(ui->typeComboBox->count()); + + primitiveTypesTypeList = Core()->getAllTypes(); + + for (const TypeDescription &thisType : primitiveTypesTypeList) { + ui->typeComboBox->addItem(thisType.type); + } + + ui->typeComboBox->insertSeparator(ui->typeComboBox->count()); + + userEnumerations = Core()->cmdList("te"); + ui->typeComboBox->addItems(userEnumerations); +} diff --git a/src/dialogs/EditVariablesDialog.h b/src/dialogs/EditVariablesDialog.h new file mode 100644 index 00000000..1afa9f2e --- /dev/null +++ b/src/dialogs/EditVariablesDialog.h @@ -0,0 +1,30 @@ +#ifndef EDITVARIABLESDIALOG_H +#define EDITVARIABLESDIALOG_H + +#include "Cutter.h" +#include + +namespace Ui { +class EditVariablesDialog; +} + +class EditVariablesDialog : public QDialog +{ + Q_OBJECT + +public: + explicit EditVariablesDialog(RVA offset, QWidget *parent = nullptr); + ~EditVariablesDialog(); + +private slots: + void applyFields(); + void updateFields(); + +private: + Ui::EditVariablesDialog *ui; + QList variables; + + void populateTypesComboBox(); +}; + +#endif // EDITVARIABLESDIALOG_H diff --git a/src/dialogs/EditVariablesDialog.ui b/src/dialogs/EditVariablesDialog.ui new file mode 100644 index 00000000..701a824f --- /dev/null +++ b/src/dialogs/EditVariablesDialog.ui @@ -0,0 +1,105 @@ + + + EditVariablesDialog + + + + 0 + 0 + 435 + 137 + + + + Dialog + + + + + + + + Modify: + + + + + + + + + + + + + Name: + + + + + + + Type: + + + + + + + true + + + 15 + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + EditVariablesDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + EditVariablesDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/dialogs/SetFunctionVarTypes.cpp b/src/dialogs/SetFunctionVarTypes.cpp deleted file mode 100644 index 85f47ff2..00000000 --- a/src/dialogs/SetFunctionVarTypes.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "SetFunctionVarTypes.h" -#include "ui_SetFunctionVarTypes.h" - -#include -#include - -SetFunctionVarTypes::SetFunctionVarTypes(QWidget *parent) : - QDialog(parent), - ui(new Ui::SetFunctionVarTypes) -{ - ui->setupUi(this); - connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(on_OkPressed())); - connect(ui->dropdownLocalVars, SIGNAL(currentIndexChanged(QString)), - SLOT(on_ComboBoxChanged(QString))); - - populateTypesComboBox(); - -} - -SetFunctionVarTypes::~SetFunctionVarTypes() -{ - delete ui; -} - -void SetFunctionVarTypes::setUserMessage(const QString userMessage) -{ - ui->userMessage->setText(userMessage); -} - -void SetFunctionVarTypes::setFcn(RAnalFunction *fcn) -{ - RListIter *iter; - RAnalVar *var; - - if (fcn == nullptr) { - ui->userMessage->setText(tr("You must be in a function to define variable types.")); - ui->labelSetTypeTo->setVisible(false); - ui->selectedTypeForVar->setVisible(false); - ui->dropdownLocalVars->setVisible(false); - - this->validFcn = false; - return; - } - ui->userMessage->setVisible(true); - ui->labelSetTypeTo->setVisible(true); - ui->selectedTypeForVar->setVisible(true); - ui->dropdownLocalVars->setVisible(true); - - this->validFcn = true; - this->fcn = fcn; - this->fcnVars = r_anal_var_all_list(Core()->core()->anal, this->fcn); - - for (iter = this->fcnVars->head; iter - && (var = static_cast(iter->data)); iter = iter->n) { - ui->dropdownLocalVars->addItem(var->name, - QVariant::fromValue(static_cast(var))); - } -} - -void SetFunctionVarTypes::on_OkPressed() -{ - - RAnalVar *selectedVar; - QVariant selectedVarVariant; - - if (!this->validFcn) { - return; - } - - selectedVarVariant = ui->dropdownLocalVars->currentData(); - selectedVar = static_cast(selectedVarVariant.value()); - - Core()->cmd(QString("afvt %1 %2") - .arg(selectedVar->name) - .arg(ui->selectedTypeForVar->currentText())); - - Core()->cmd(QString("afvn %1 %2") - .arg(ui->newVarName->text().replace(' ', '_')) - .arg(ui->dropdownLocalVars->currentText())); -} - -void SetFunctionVarTypes::on_ComboBoxChanged(QString varName) -{ - ui->newVarName->setText(varName); -} - - -void SetFunctionVarTypes::populateTypesComboBox() -{ - //gets all loaded types, structures and enums and puts them in a list - - QStringList userStructures; - QStringList userEnumerations; - QList primitiveTypesTypeList; - - userStructures = Core()->cmdList("ts"); - ui->selectedTypeForVar->addItems(userStructures); - ui->selectedTypeForVar->insertSeparator(ui->selectedTypeForVar->count()); - - primitiveTypesTypeList = Core()->getAllTypes(); - - for (const TypeDescription &thisType : primitiveTypesTypeList) { - ui->selectedTypeForVar->addItem(thisType.type); - } - - ui->selectedTypeForVar->insertSeparator(ui->selectedTypeForVar->count()); - - userEnumerations = Core()->cmdList("te"); - ui->selectedTypeForVar->addItems(userEnumerations); - - return; - -} diff --git a/src/dialogs/SetFunctionVarTypes.h b/src/dialogs/SetFunctionVarTypes.h deleted file mode 100644 index 6f702a14..00000000 --- a/src/dialogs/SetFunctionVarTypes.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SETFUNCTIONVARTYPES_H -#define SETFUNCTIONVARTYPES_H - -#include "Cutter.h" -#include - -namespace Ui { -class SetFunctionVarTypes; -} - -class SetFunctionVarTypes : public QDialog -{ - Q_OBJECT - -public: - explicit SetFunctionVarTypes(QWidget *parent = nullptr); - ~SetFunctionVarTypes(); - - void setUserMessage(const QString userMessage); - void setFcn(RAnalFunction *fcn); - -public slots: - void on_OkPressed(); - void on_ComboBoxChanged(QString varName); - - -private: - RList *fcnVars; - RAnalFunction *fcn; - Ui::SetFunctionVarTypes *ui; - bool validFcn; - void populateTypesComboBox(); - -}; - -#endif // SETFUNCTIONVARTYPES_H diff --git a/src/dialogs/SetFunctionVarTypes.ui b/src/dialogs/SetFunctionVarTypes.ui deleted file mode 100644 index 07511ad1..00000000 --- a/src/dialogs/SetFunctionVarTypes.ui +++ /dev/null @@ -1,156 +0,0 @@ - - - SetFunctionVarTypes - - - - 0 - 0 - 636 - 327 - - - - Dialog - - - - - 10 - 290 - 621 - 32 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - 20 - 10 - 601 - 17 - - - - - - - - - - 20 - 60 - 271 - 31 - - - - - - - 30 - 180 - 91 - 17 - - - - Set Type To: - - - - - - 30 - 210 - 261 - 31 - - - - true - - - 15 - - - - - - 30 - 110 - 241 - 17 - - - - Set Name To: - - - - - - 20 - 30 - 67 - 17 - - - - Modify: - - - - - - 30 - 140 - 261 - 31 - - - - - - - - buttonBox - accepted() - SetFunctionVarTypes - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - SetFunctionVarTypes - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/src/menus/DisassemblyContextMenu.cpp b/src/menus/DisassemblyContextMenu.cpp index 379896de..270bb89c 100644 --- a/src/menus/DisassemblyContextMenu.cpp +++ b/src/menus/DisassemblyContextMenu.cpp @@ -5,7 +5,7 @@ #include "dialogs/FlagDialog.h" #include "dialogs/RenameDialog.h" #include "dialogs/XrefsDialog.h" -#include "dialogs/SetFunctionVarTypes.h" +#include "dialogs/EditVariablesDialog.h" #include "dialogs/SetToDataDialog.h" #include "dialogs/EditFunctionDialog.h" #include @@ -640,20 +640,15 @@ void DisassemblyContextMenu::on_actionRenameUsedHere_triggered() 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)); + if (!fcn) { + QMessageBox::critical(this, tr("Re-type function local vars"), tr("You must be in a function to define variable types.")); + return; } - dialog->setFcn(fcn); - - dialog->exec(); + EditVariablesDialog dialog(Core()->getOffset(), this); + dialog.exec(); } void DisassemblyContextMenu::on_actionXRefs_triggered()