From 09e4bf348e5c6df97d6accd905ac5c861cff18c4 Mon Sep 17 00:00:00 2001 From: fcasal Date: Tue, 6 Mar 2018 17:21:48 +0000 Subject: [PATCH] Added typeswidget (#358) --- src/Cutter.cpp | 23 ++++++ src/Cutter.h | 9 ++ src/Cutter.pro | 3 + src/MainWindow.cpp | 3 + src/MainWindow.h | 2 + src/MainWindow.ui | 12 +++ src/widgets/TypesWidget.cpp | 158 ++++++++++++++++++++++++++++++++++++ src/widgets/TypesWidget.h | 89 ++++++++++++++++++++ src/widgets/TypesWidget.ui | 58 +++++++++++++ 9 files changed, 357 insertions(+) create mode 100644 src/widgets/TypesWidget.cpp create mode 100644 src/widgets/TypesWidget.h create mode 100644 src/widgets/TypesWidget.ui diff --git a/src/Cutter.cpp b/src/Cutter.cpp index 905c0a8e..f419b0b2 100644 --- a/src/Cutter.cpp +++ b/src/Cutter.cpp @@ -1284,6 +1284,29 @@ QList CutterCore::getAllVTables() return ret; } +QList CutterCore::getAllTypes() +{ + CORE_LOCK(); + QList ret; + + QJsonArray typesArray = cmdj("tj").array(); + + foreach (QJsonValue value, typesArray) + { + QJsonObject typeObject = value.toObject(); + + TypeDescription exp; + + exp.type = typeObject["type"].toString(); + exp.size = typeObject["size"].toVariant().toULongLong(); + exp.format = typeObject["format"].toString(); + + ret << exp; + } + + return ret; +} + QList CutterCore::getXRefs(RVA addr, bool to, bool whole_function, const QString &filterType) { QList ret = QList(); diff --git a/src/Cutter.h b/src/Cutter.h index d41f37e0..e638158c 100644 --- a/src/Cutter.h +++ b/src/Cutter.h @@ -91,6 +91,13 @@ struct ExportDescription QString flag_name; }; +struct TypeDescription +{ + QString type; + int size; + QString format; +}; + struct SymbolDescription { RVA vaddr; @@ -234,6 +241,7 @@ Q_DECLARE_METATYPE(const ClassMethodDescription *) Q_DECLARE_METATYPE(const ClassFieldDescription *) Q_DECLARE_METATYPE(ResourcesDescription) Q_DECLARE_METATYPE(VTableDescription) +Q_DECLARE_METATYPE(TypeDescription) class CutterCore: public QObject { @@ -367,6 +375,7 @@ public: QList getAllClasses(); QList getAllResources(); QList getAllVTables(); + QList getAllTypes(); 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 beb5d5b8..67ddcc6c 100644 --- a/src/Cutter.pro +++ b/src/Cutter.pro @@ -130,6 +130,7 @@ SOURCES += \ widgets/ClassesWidget.cpp \ widgets/ResourcesWidget.cpp \ widgets/VTablesWidget.cpp \ + widgets/TypesWidget.cpp \ CutterApplication.cpp \ utils/JupyterConnection.cpp \ widgets/JupyterWidget.cpp \ @@ -195,6 +196,7 @@ HEADERS += \ widgets/ResourcesWidget.h \ CutterApplication.h \ widgets/VTablesWidget.h \ + widgets/TypesWidget.h \ utils/JupyterConnection.h \ widgets/JupyterWidget.h \ utils/PythonAPI.h \ @@ -235,6 +237,7 @@ FORMS += \ widgets/PseudocodeWidget.ui \ widgets/ClassesWidget.ui \ widgets/VTablesWidget.ui \ + widgets/TypesWidget.ui \ widgets/JupyterWidget.ui RESOURCES += \ diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index a343f9b8..737cd74e 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -48,6 +48,7 @@ #include "widgets/CommentsWidget.h" #include "widgets/ImportsWidget.h" #include "widgets/ExportsWidget.h" +#include "widgets/TypesWidget.h" #include "widgets/SymbolsWidget.h" #include "widgets/StringsWidget.h" #include "widgets/SectionsDock.h" @@ -215,6 +216,7 @@ void MainWindow::initUI() ADD_DOCK(FunctionsWidget, functionsDock, ui->actionFunctions); ADD_DOCK(ImportsWidget, importsDock, ui->actionImports); ADD_DOCK(ExportsWidget, exportsDock, ui->actionExports); + ADD_DOCK(TypesWidget, typesDock, ui->actionTypes); ADD_DOCK(SymbolsWidget, symbolsDock, ui->actionSymbols); ADD_DOCK(RelocsWidget, relocsDock, ui->actionRelocs); ADD_DOCK(CommentsWidget, commentsDock, ui->actionComments); @@ -539,6 +541,7 @@ void MainWindow::restoreDocks() tabifyDockWidget(dashboardDock, relocsDock); tabifyDockWidget(dashboardDock, importsDock); tabifyDockWidget(dashboardDock, exportsDock); + tabifyDockWidget(dashboardDock, typesDock); tabifyDockWidget(dashboardDock, symbolsDock); tabifyDockWidget(dashboardDock, classesDock); tabifyDockWidget(dashboardDock, resourcesDock); diff --git a/src/MainWindow.h b/src/MainWindow.h index 7f098fb9..e1691fbf 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -39,6 +39,7 @@ class DisassemblerGraphView; class ClassesWidget; class ResourcesWidget; class VTablesWidget; +class TypesWidget; #ifdef CUTTER_ENABLE_JUPYTER class JupyterWidget; #endif @@ -175,6 +176,7 @@ private: FunctionsWidget *functionsDock = nullptr; ImportsWidget *importsDock = nullptr; ExportsWidget *exportsDock = nullptr; + TypesWidget *typesDock = nullptr; SymbolsWidget *symbolsDock = nullptr; RelocsWidget *relocsDock = nullptr; CommentsWidget *commentsDock = nullptr; diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 935a4621..d19e92e8 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -251,6 +251,7 @@ border-top: 0px; + @@ -1049,6 +1050,17 @@ QToolButton:pressed { Show/Hide VTables panel + + + true + + + Types + + + Show/Hide Types panel + + true diff --git a/src/widgets/TypesWidget.cpp b/src/widgets/TypesWidget.cpp new file mode 100644 index 00000000..9392387e --- /dev/null +++ b/src/widgets/TypesWidget.cpp @@ -0,0 +1,158 @@ +#include "TypesWidget.h" +#include "ui_TypesWidget.h" +#include "MainWindow.h" +#include "utils/Helpers.h" + +TypesModel::TypesModel(QList *types, QObject *parent) + : QAbstractListModel(parent), + types(types) +{ +} + +int TypesModel::rowCount(const QModelIndex &) const +{ + return types->count(); +} + +int TypesModel::columnCount(const QModelIndex &) const +{ + return Columns::COUNT; +} + +QVariant TypesModel::data(const QModelIndex &index, int role) const +{ + if (index.row() >= types->count()) + return QVariant(); + + const TypeDescription &exp = types->at(index.row()); + + switch (role) + { + case Qt::DisplayRole: + switch (index.column()) + { + case TYPE: + return exp.type; + case SIZE: + return exp.size; + case FORMAT: + return exp.format; + default: + return QVariant(); + } + case TypeDescriptionRole: + return QVariant::fromValue(exp); + default: + return QVariant(); + } +} + +QVariant TypesModel::headerData(int section, Qt::Orientation, int role) const +{ + switch (role) + { + case Qt::DisplayRole: + switch (section) + { + case TYPE: + return tr("Type"); + case SIZE: + return tr("Size"); + case FORMAT: + return tr("Format"); + default: + return QVariant(); + } + default: + return QVariant(); + } +} + +void TypesModel::beginReloadTypes() +{ + beginResetModel(); +} + +void TypesModel::endReloadTypes() +{ + endResetModel(); +} + +TypesSortFilterProxyModel::TypesSortFilterProxyModel(TypesModel *source_model, QObject *parent) + : QSortFilterProxyModel(parent) +{ + setSourceModel(source_model); +} + +bool TypesSortFilterProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const +{ + QModelIndex index = sourceModel()->index(row, 0, parent); + TypeDescription exp = index.data(TypesModel::TypeDescriptionRole).value(); + return exp.type.contains(filterRegExp()); +} + +bool TypesSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const +{ + TypeDescription left_exp = left.data(TypesModel::TypeDescriptionRole).value(); + TypeDescription right_exp = right.data(TypesModel::TypeDescriptionRole).value(); + + switch (left.column()) + { + case TypesModel::TYPE: + return left_exp.type < right_exp.type; + case TypesModel::SIZE: + return left_exp.size < right_exp.size; + case TypesModel::FORMAT: + return left_exp.format < right_exp.format; + default: + break; + } + + return left_exp.size < right_exp.size; +} + + + +TypesWidget::TypesWidget(MainWindow *main, QWidget *parent) : + QDockWidget(parent), + ui(new Ui::TypesWidget), + main(main) +{ + ui->setupUi(this); + + // Radare core found in: + this->main = main; + + types_model = new TypesModel(&types, this); + types_proxy_model = new TypesSortFilterProxyModel(types_model, this); + ui->typesTreeView->setModel(types_proxy_model); + ui->typesTreeView->sortByColumn(TypesModel::TYPE, Qt::AscendingOrder); + + setScrollMode(); + + connect(Core(), SIGNAL(refreshAll()), this, SLOT(refreshTypes())); +} + +TypesWidget::~TypesWidget() {} + +void TypesWidget::refreshTypes() +{ + types_model->beginReloadTypes(); + types = CutterCore::getInstance()->getAllTypes(); + types_model->endReloadTypes(); + + ui->typesTreeView->resizeColumnToContents(0); + ui->typesTreeView->resizeColumnToContents(1); + ui->typesTreeView->resizeColumnToContents(2); +} + +void TypesWidget::setScrollMode() +{ + qhelpers::setVerticalScrollMode(ui->typesTreeView); +} + +void TypesWidget::on_typesTreeView_doubleClicked(const QModelIndex &index) +{ + // TypeDescription exp = index.data(TypesModel::TypeDescriptionRole).value(); + // CutterCore::getInstance()->seek(exp.vaddr); +} diff --git a/src/widgets/TypesWidget.h b/src/widgets/TypesWidget.h new file mode 100644 index 00000000..4b73fca2 --- /dev/null +++ b/src/widgets/TypesWidget.h @@ -0,0 +1,89 @@ +#ifndef TYPESWIDGET_H +#define TYPESWIDGET_H + +#include + +#include "Cutter.h" + +#include +#include +#include + +class MainWindow; +class QTreeWidget; + +namespace Ui +{ + class TypesWidget; +} + + +class MainWindow; +class QTreeWidgetItem; + + +class TypesModel: public QAbstractListModel +{ + Q_OBJECT + +private: + QList *types; + +public: + enum Columns { TYPE = 0, SIZE, FORMAT, COUNT }; + static const int TypeDescriptionRole = Qt::UserRole; + + TypesModel(QList *types, QObject *parent = 0); + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + + QVariant data(const QModelIndex &index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + void beginReloadTypes(); + void endReloadTypes(); +}; + + + +class TypesSortFilterProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT + +public: + TypesSortFilterProxyModel(TypesModel *source_model, QObject *parent = 0); + +protected: + bool filterAcceptsRow(int row, const QModelIndex &parent) const override; + bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; +}; + + + +class TypesWidget : public QDockWidget +{ + Q_OBJECT + +public: + explicit TypesWidget(MainWindow *main, QWidget *parent = 0); + ~TypesWidget(); + +private slots: + void on_typesTreeView_doubleClicked(const QModelIndex &index); + + void refreshTypes(); + +private: + std::unique_ptr ui; + MainWindow *main; + + TypesModel *types_model; + TypesSortFilterProxyModel *types_proxy_model; + QList types; + + void setScrollMode(); +}; + + +#endif // TYPESWIDGET_H diff --git a/src/widgets/TypesWidget.ui b/src/widgets/TypesWidget.ui new file mode 100644 index 00000000..19e5cc2a --- /dev/null +++ b/src/widgets/TypesWidget.ui @@ -0,0 +1,58 @@ + + + TypesWidget + + + + 0 + 0 + 400 + 300 + + + + Types + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QTreeView::item +{ + padding-top: 1px; + padding-bottom: 1px; +} + + + QFrame::NoFrame + + + 0 + + + 8 + + + true + + + + + + + + +