Cleanup EditVariablesDialog (#1007)

Originally SetFunctionVarTypes
This commit is contained in:
Florian Märkl 2018-12-19 09:39:23 +01:00 committed by xarkes
parent c8d8e667fb
commit 99b1fde47d
10 changed files with 252 additions and 319 deletions

View File

@ -856,6 +856,29 @@ QList<RegisterRefDescription> CutterCore::getRegisterRefs()
return ret;
}
QList<VariableDescription> CutterCore::getVariables(RVA at)
{
QList<VariableDescription> 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();

View File

@ -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<ProcessDescription> getAllProcesses();
QList<RegisterRefDescription> getRegisterRefs();
QJsonObject getRegisterJson();
QList<VariableDescription> getVariables(RVA at);
QList<XrefDescription> getXRefs(RVA addr, bool to, bool whole_function,
const QString &filterType = QString::null);

View File

@ -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 \

View File

@ -0,0 +1,76 @@
#include "EditVariablesDialog.h"
#include "ui_EditVariablesDialog.h"
#include <QMetaType>
#include <QComboBox>
#include <QMetaType>
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<VariableDescription>();
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<VariableDescription>();
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<TypeDescription> 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);
}

View File

@ -0,0 +1,30 @@
#ifndef EDITVARIABLESDIALOG_H
#define EDITVARIABLESDIALOG_H
#include "Cutter.h"
#include <QDialog>
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<VariableDescription> variables;
void populateTypesComboBox();
};
#endif // EDITVARIABLESDIALOG_H

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditVariablesDialog</class>
<widget class="QDialog" name="EditVariablesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>435</width>
<height>137</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Modify:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="dropdownLocalVars"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="nameEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="nameLabel">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelSetTypeTo">
<property name="text">
<string>Type:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="typeComboBox">
<property name="editable">
<bool>true</bool>
</property>
<property name="maxVisibleItems">
<number>15</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>EditVariablesDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>EditVariablesDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -1,113 +0,0 @@
#include "SetFunctionVarTypes.h"
#include "ui_SetFunctionVarTypes.h"
#include <QMetaType>
#include <QComboBox>
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<RAnalVar *>(iter->data)); iter = iter->n) {
ui->dropdownLocalVars->addItem(var->name,
QVariant::fromValue(static_cast<void *>(var)));
}
}
void SetFunctionVarTypes::on_OkPressed()
{
RAnalVar *selectedVar;
QVariant selectedVarVariant;
if (!this->validFcn) {
return;
}
selectedVarVariant = ui->dropdownLocalVars->currentData();
selectedVar = static_cast<RAnalVar *>(selectedVarVariant.value<void *>());
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<TypeDescription> 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;
}

View File

@ -1,36 +0,0 @@
#ifndef SETFUNCTIONVARTYPES_H
#define SETFUNCTIONVARTYPES_H
#include "Cutter.h"
#include <QDialog>
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

View File

@ -1,156 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SetFunctionVarTypes</class>
<widget class="QDialog" name="SetFunctionVarTypes">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>636</width>
<height>327</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>10</x>
<y>290</y>
<width>621</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QLabel" name="userMessage">
<property name="geometry">
<rect>
<x>20</x>
<y>10</y>
<width>601</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QComboBox" name="dropdownLocalVars">
<property name="geometry">
<rect>
<x>20</x>
<y>60</y>
<width>271</width>
<height>31</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="labelSetTypeTo">
<property name="geometry">
<rect>
<x>30</x>
<y>180</y>
<width>91</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Set Type To:</string>
</property>
</widget>
<widget class="QComboBox" name="selectedTypeForVar">
<property name="geometry">
<rect>
<x>30</x>
<y>210</y>
<width>261</width>
<height>31</height>
</rect>
</property>
<property name="editable">
<bool>true</bool>
</property>
<property name="maxVisibleItems">
<number>15</number>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>30</x>
<y>110</y>
<width>241</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Set Name To:</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>20</x>
<y>30</y>
<width>67</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Modify:</string>
</property>
</widget>
<widget class="QLineEdit" name="newVarName">
<property name="geometry">
<rect>
<x>30</x>
<y>140</y>
<width>261</width>
<height>31</height>
</rect>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SetFunctionVarTypes</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SetFunctionVarTypes</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -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 <QtCore>
@ -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()