Added typeswidget (#358)

This commit is contained in:
fcasal 2018-03-06 17:21:48 +00:00 committed by xarkes
parent 93be7f4907
commit 09e4bf348e
9 changed files with 357 additions and 0 deletions

View File

@ -1284,6 +1284,29 @@ QList<VTableDescription> CutterCore::getAllVTables()
return ret;
}
QList<TypeDescription> CutterCore::getAllTypes()
{
CORE_LOCK();
QList<TypeDescription> 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<XrefDescription> CutterCore::getXRefs(RVA addr, bool to, bool whole_function, const QString &filterType)
{
QList<XrefDescription> ret = QList<XrefDescription>();

View File

@ -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<ClassDescription> getAllClasses();
QList<ResourcesDescription> getAllResources();
QList<VTableDescription> getAllVTables();
QList<TypeDescription> getAllTypes();
QList<XrefDescription> getXRefs(RVA addr, bool to, bool whole_function, const QString &filterType = QString::null);

View File

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

View File

@ -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);

View File

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

View File

@ -251,6 +251,7 @@ border-top: 0px;
<addaction name="actionSDBBrowser"/>
<addaction name="actionResources"/>
<addaction name="actionVTables"/>
<addaction name="actionTypes"/>
<addaction name="separator"/>
<addaction name="actionRelocs"/>
<addaction name="actionStrings"/>
@ -1049,6 +1050,17 @@ QToolButton:pressed {
<string>Show/Hide VTables panel</string>
</property>
</action>
<action name="actionTypes">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Types</string>
</property>
<property name="toolTip">
<string>Show/Hide Types panel</string>
</property>
</action>
<action name="actionJupyter">
<property name="checkable">
<bool>true</bool>

158
src/widgets/TypesWidget.cpp Normal file
View File

@ -0,0 +1,158 @@
#include "TypesWidget.h"
#include "ui_TypesWidget.h"
#include "MainWindow.h"
#include "utils/Helpers.h"
TypesModel::TypesModel(QList<TypeDescription> *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<TypeDescription>();
return exp.type.contains(filterRegExp());
}
bool TypesSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
TypeDescription left_exp = left.data(TypesModel::TypeDescriptionRole).value<TypeDescription>();
TypeDescription right_exp = right.data(TypesModel::TypeDescriptionRole).value<TypeDescription>();
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<TypeDescription>();
// CutterCore::getInstance()->seek(exp.vaddr);
}

89
src/widgets/TypesWidget.h Normal file
View File

@ -0,0 +1,89 @@
#ifndef TYPESWIDGET_H
#define TYPESWIDGET_H
#include <memory>
#include "Cutter.h"
#include <QAbstractListModel>
#include <QSortFilterProxyModel>
#include <QDockWidget>
class MainWindow;
class QTreeWidget;
namespace Ui
{
class TypesWidget;
}
class MainWindow;
class QTreeWidgetItem;
class TypesModel: public QAbstractListModel
{
Q_OBJECT
private:
QList<TypeDescription> *types;
public:
enum Columns { TYPE = 0, SIZE, FORMAT, COUNT };
static const int TypeDescriptionRole = Qt::UserRole;
TypesModel(QList<TypeDescription> *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::TypesWidget> ui;
MainWindow *main;
TypesModel *types_model;
TypesSortFilterProxyModel *types_proxy_model;
QList<TypeDescription> types;
void setScrollMode();
};
#endif // TYPESWIDGET_H

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TypesWidget</class>
<widget class="QDockWidget" name="TypesWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Types</string>
</property>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTreeView" name="typesTreeView">
<property name="styleSheet">
<string notr="true">QTreeView::item
{
padding-top: 1px;
padding-bottom: 1px;
}</string>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="indentation">
<number>8</number>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>