Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added load, delete and export features in the Types Widget #1158

Merged
merged 11 commits into from
Feb 11, 2019
2 changes: 1 addition & 1 deletion radare2
21 changes: 17 additions & 4 deletions src/Cutter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2208,7 +2208,7 @@ QList<TypeDescription> CutterCore::getAllUnions()
TypeDescription exp;
exp.type = value.toString();
exp.size = 0;
exp.category = tr("Union");
exp.category = "Union";
ret << exp;
}

Expand All @@ -2225,7 +2225,7 @@ QList<TypeDescription> CutterCore::getAllStructs()
TypeDescription exp;
exp.type = value.toString();
exp.size = 0;
exp.category = tr("Struct");
exp.category = "Struct";
ret << exp;
}

Expand All @@ -2242,7 +2242,7 @@ QList<TypeDescription> CutterCore::getAllEnums()
TypeDescription exp;
exp.type = key;
exp.size = 0;
exp.category = tr("Enum");
exp.category = "Enum";
ret << exp;
}

Expand All @@ -2259,13 +2259,26 @@ QList<TypeDescription> CutterCore::getAllTypedefs()
TypeDescription exp;
exp.type = key;
exp.size = 0;
exp.category = tr("Typedef");
exp.category = "Typedef";
ret << exp;
}

return ret;
}

QString CutterCore::addTypes(const char *str)
{
char *error_msg = nullptr;
char *parsed = r_parse_c_string(core_->anal, str, &error_msg);

if (!parsed && error_msg) {
return QString(error_msg);
}

sdb_query_lines(core_->anal->sdb_types, parsed);
return QString();
}

QList<SearchDescription> CutterCore::getAllSearch(QString search_for, QString space)
{
CORE_LOCK();
Expand Down
12 changes: 12 additions & 0 deletions src/Cutter.h
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,18 @@ class CutterCore: public QObject
*/
QList<TypeDescription> getAllTypedefs();

/*!
* \brief Adds new types
* It first uses the r_parse_c_string() function from radare2 API to parse the
* supplied C file (in the form of a string). If there were errors, they are displayed.
* If there were no errors, it uses sdb_query_lines() function from radare2 API
* to save the parsed types returned by r_parse_c_string()
* \param str Contains the definition of the data types
* \return returns an empty QString if there was no error, else returns the error
*/
QString addTypes(const char *str);
QString addTypes(const QString &str) { return addTypes(str.toUtf8().constData()); }

QList<MemoryMapDescription> getMemoryMap();
QList<SearchDescription> getAllSearch(QString search_for, QString space);
BlockStatistics getBlockStatistics(unsigned int blocksCount);
Expand Down
9 changes: 6 additions & 3 deletions src/Cutter.pro
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,8 @@ SOURCES += \
common/RefreshDeferrer.cpp \
dialogs/WelcomeDialog.cpp \
RunScriptTask.cpp \
dialogs/EditMethodDialog.cpp
dialogs/EditMethodDialog.cpp \
dialogs/LoadNewTypesDialog.cpp

HEADERS += \
Cutter.h \
Expand Down Expand Up @@ -337,7 +338,8 @@ HEADERS += \
dialogs/WelcomeDialog.h \
RunScriptTask.h \
common/Json.h \
dialogs/EditMethodDialog.h
dialogs/EditMethodDialog.h \
dialogs/LoadNewTypesDialog.h

FORMS += \
dialogs/AboutDialog.ui \
Expand Down Expand Up @@ -397,7 +399,8 @@ FORMS += \
widgets/ComboQuickFilterView.ui \
dialogs/HexdumpRangeDialog.ui \
dialogs/WelcomeDialog.ui \
dialogs/EditMethodDialog.ui
dialogs/EditMethodDialog.ui \
dialogs/LoadNewTypesDialog.ui

RESOURCES += \
resources.qrc \
Expand Down
71 changes: 71 additions & 0 deletions src/dialogs/LoadNewTypesDialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include "dialogs/LoadNewTypesDialog.h"
#include "ui_LoadNewTypesDialog.h"

#include "Cutter.h"
#include "common/Configuration.h"
#include "widgets/TypesWidget.h"

#include <QFileDialog>
#include <QTemporaryFile>

LoadNewTypesDialog::LoadNewTypesDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::LoadNewTypesDialog)
{
ui->setupUi(this);
ui->plainTextEdit->setPlainText("");
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
}

LoadNewTypesDialog::~LoadNewTypesDialog() {}

void LoadNewTypesDialog::on_selectFileButton_clicked()
{
QString filename = QFileDialog::getOpenFileName(this, tr("Select file"), Config()->getRecentFolder(), "Header files (*.h *.hpp);;All files (*)");
if (filename.isEmpty()) {
return;
}
Config()->setRecentFolder(QFileInfo(filename).absolutePath());
QFile file(filename);
if (!file.open(QIODevice::ReadOnly)) {
QMessageBox popup(this);
popup.setWindowTitle(tr("Error"));
popup.setText(file.errorString());
popup.setStandardButtons(QMessageBox::Ok);
popup.exec();
on_selectFileButton_clicked();
return;
}
ui->filenameLineEdit->setText(filename);
ui->plainTextEdit->setPlainText(file.readAll());
}

void LoadNewTypesDialog::on_plainTextEdit_textChanged()
{
if (ui->plainTextEdit->toPlainText().isEmpty()) {
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
} else {
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
}
}

void LoadNewTypesDialog::done(int r)
{
if (r == QDialog::Accepted) {
QString error = Core()->addTypes(ui->plainTextEdit->toPlainText());
if (error.isEmpty()) {
emit newTypesLoaded();
QDialog::done(r);
return;
}

QMessageBox popup(this);
popup.setWindowTitle(tr("Error"));
popup.setText(tr("There was some error while loading new types"));
popup.setDetailedText(error);
popup.setStandardButtons(QMessageBox::Ok);
popup.exec();
} else {
QDialog::done(r);
}
}
49 changes: 49 additions & 0 deletions src/dialogs/LoadNewTypesDialog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#ifndef LOADNEWTYPESDIALOG_H
#define LOADNEWTYPESDIALOG_H

#include <QDialog>
#include <memory>

namespace Ui {
class LoadNewTypesDialog;
}

class LoadNewTypesDialog : public QDialog
{
Q_OBJECT

public:
explicit LoadNewTypesDialog(QWidget *parent = nullptr);
~LoadNewTypesDialog();

private slots:
/*!
* \brief Executed when the user clicks the selectFileButton
* Opens a File Dialog from where the user can select a file from where
* the types will be loaded.
*/
void on_selectFileButton_clicked();

/*!
* \brief Executed whenever the text inside the textbox changes
* When the text box is empty, the OK button is disabled.
*/
void on_plainTextEdit_textChanged();

/*!
* \brief done Closes the dialog and sets its result code to r
* \param r The value which will be returned by exec()
*/
void done(int r) override;
gauravkghildiyal marked this conversation as resolved.
Show resolved Hide resolved

private:
std::unique_ptr<Ui::LoadNewTypesDialog> ui;

signals:
/*!
* \brief Emitted when new types are loaded
*/
void newTypesLoaded();
};

#endif // LOADNEWTYPESDIALOG_H
99 changes: 99 additions & 0 deletions src/dialogs/LoadNewTypesDialog.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LoadNewTypesDialog</class>
<widget class="QDialog" name="LoadNewTypesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="filenameLabel">
<property name="text">
<string>Load From File:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="filenameLineEdit">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="selectFileButton">
<property name="text">
<string>Select File</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPlainTextEdit" name="plainTextEdit">
<property name="plainText">
<string/>
</property>
<property name="placeholderText">
<string>Enter Types Manually</string>
</property>
</widget>
</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>LoadNewTypesDialog</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>LoadNewTypesDialog</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>
Loading