Added headers widget (#499)

This commit is contained in:
fcasal 2018-05-21 18:34:41 +01:00 committed by xarkes
parent 55be4efb8c
commit 7fdfad32f7
9 changed files with 346 additions and 1 deletions

View File

@ -1020,6 +1020,29 @@ QList<SymbolDescription> CutterCore::getAllSymbols()
return ret; return ret;
} }
QList<HeaderDescription> CutterCore::getAllHeaders()
{
CORE_LOCK();
QList<HeaderDescription> ret;
QJsonArray headersArray = cmdj("ihj").array();
for (QJsonValue value : headersArray) {
QJsonObject headerObject = value.toObject();
HeaderDescription header;
header.vaddr = headerObject["vaddr"].toVariant().toULongLong();
header.paddr = headerObject["paddr"].toVariant().toULongLong();
header.value = headerObject["comment"].toString();
header.name = headerObject["name"].toString();
ret << header;
}
return ret;
}
QList<CommentDescription> CutterCore::getAllComments(const QString &filterType) QList<CommentDescription> CutterCore::getAllComments(const QString &filterType)
{ {
CORE_LOCK(); CORE_LOCK();

View File

@ -108,6 +108,14 @@ struct ExportDescription {
QString flag_name; QString flag_name;
}; };
struct HeaderDescription
{
RVA vaddr;
RVA paddr;
QString value;
QString name;
};
struct TypeDescription { struct TypeDescription {
QString type; QString type;
int size; int size;
@ -275,6 +283,7 @@ Q_DECLARE_METATYPE(const ClassFieldDescription *)
Q_DECLARE_METATYPE(ResourcesDescription) Q_DECLARE_METATYPE(ResourcesDescription)
Q_DECLARE_METATYPE(VTableDescription) Q_DECLARE_METATYPE(VTableDescription)
Q_DECLARE_METATYPE(TypeDescription) Q_DECLARE_METATYPE(TypeDescription)
Q_DECLARE_METATYPE(HeaderDescription)
Q_DECLARE_METATYPE(SearchDescription) Q_DECLARE_METATYPE(SearchDescription)
Q_DECLARE_METATYPE(SectionDescription) Q_DECLARE_METATYPE(SectionDescription)
@ -429,6 +438,7 @@ public:
QList<ImportDescription> getAllImports(); QList<ImportDescription> getAllImports();
QList<ExportDescription> getAllExports(); QList<ExportDescription> getAllExports();
QList<SymbolDescription> getAllSymbols(); QList<SymbolDescription> getAllSymbols();
QList<HeaderDescription> getAllHeaders();
QList<CommentDescription> getAllComments(const QString &filterType); QList<CommentDescription> getAllComments(const QString &filterType);
QList<RelocDescription> getAllRelocs(); QList<RelocDescription> getAllRelocs();
QList<StringDescription> getAllStrings(); QList<StringDescription> getAllStrings();

View File

@ -146,6 +146,7 @@ SOURCES += \
widgets/ResourcesWidget.cpp \ widgets/ResourcesWidget.cpp \
widgets/VTablesWidget.cpp \ widgets/VTablesWidget.cpp \
widgets/TypesWidget.cpp \ widgets/TypesWidget.cpp \
widgets/HeadersWidget.cpp \
widgets/SearchWidget.cpp \ widgets/SearchWidget.cpp \
CutterApplication.cpp \ CutterApplication.cpp \
utils/JupyterConnection.cpp \ utils/JupyterConnection.cpp \
@ -219,6 +220,7 @@ HEADERS += \
CutterApplication.h \ CutterApplication.h \
widgets/VTablesWidget.h \ widgets/VTablesWidget.h \
widgets/TypesWidget.h \ widgets/TypesWidget.h \
widgets/HeadersWidget.h \
widgets/SearchWidget.h \ widgets/SearchWidget.h \
utils/JupyterConnection.h \ utils/JupyterConnection.h \
widgets/JupyterWidget.h \ widgets/JupyterWidget.h \
@ -267,6 +269,7 @@ FORMS += \
widgets/ClassesWidget.ui \ widgets/ClassesWidget.ui \
widgets/VTablesWidget.ui \ widgets/VTablesWidget.ui \
widgets/TypesWidget.ui \ widgets/TypesWidget.ui \
widgets/HeadersWidget.ui \
widgets/SearchWidget.ui \ widgets/SearchWidget.ui \
widgets/JupyterWidget.ui \ widgets/JupyterWidget.ui \
dialogs/R2PluginsDialog.ui \ dialogs/R2PluginsDialog.ui \

View File

@ -68,6 +68,7 @@
#include "widgets/ResourcesWidget.h" #include "widgets/ResourcesWidget.h"
#include "widgets/VTablesWidget.h" #include "widgets/VTablesWidget.h"
#include "widgets/JupyterWidget.h" #include "widgets/JupyterWidget.h"
#include "widgets/HeadersWidget.h"
// graphics // graphics
#include <QGraphicsEllipseItem> #include <QGraphicsEllipseItem>
@ -167,6 +168,7 @@ void MainWindow::initUI()
functionsDock = new FunctionsWidget(this, ui->actionFunctions); functionsDock = new FunctionsWidget(this, ui->actionFunctions);
importsDock = new ImportsWidget(this, ui->actionImports); importsDock = new ImportsWidget(this, ui->actionImports);
exportsDock = new ExportsWidget(this, ui->actionExports); exportsDock = new ExportsWidget(this, ui->actionExports);
headersDock = new HeadersWidget(this, ui->actionHeaders);
typesDock = new TypesWidget(this, ui->actionTypes); typesDock = new TypesWidget(this, ui->actionTypes);
searchDock = new SearchWidget(this, ui->actionSearch); searchDock = new SearchWidget(this, ui->actionSearch);
symbolsDock = new SymbolsWidget(this, ui->actionSymbols); symbolsDock = new SymbolsWidget(this, ui->actionSymbols);
@ -461,6 +463,7 @@ void MainWindow::restoreDocks()
tabifyDockWidget(dashboardDock, exportsDock); tabifyDockWidget(dashboardDock, exportsDock);
tabifyDockWidget(dashboardDock, typesDock); tabifyDockWidget(dashboardDock, typesDock);
tabifyDockWidget(dashboardDock, searchDock); tabifyDockWidget(dashboardDock, searchDock);
tabifyDockWidget(dashboardDock, headersDock);
tabifyDockWidget(dashboardDock, symbolsDock); tabifyDockWidget(dashboardDock, symbolsDock);
tabifyDockWidget(dashboardDock, classesDock); tabifyDockWidget(dashboardDock, classesDock);
tabifyDockWidget(dashboardDock, resourcesDock); tabifyDockWidget(dashboardDock, resourcesDock);

View File

@ -40,6 +40,7 @@ class ClassesWidget;
class ResourcesWidget; class ResourcesWidget;
class VTablesWidget; class VTablesWidget;
class TypesWidget; class TypesWidget;
class HeadersWidget;
class SearchWidget; class SearchWidget;
#ifdef CUTTER_ENABLE_JUPYTER #ifdef CUTTER_ENABLE_JUPYTER
class JupyterWidget; class JupyterWidget;
@ -183,6 +184,7 @@ private:
FunctionsWidget *functionsDock = nullptr; FunctionsWidget *functionsDock = nullptr;
ImportsWidget *importsDock = nullptr; ImportsWidget *importsDock = nullptr;
ExportsWidget *exportsDock = nullptr; ExportsWidget *exportsDock = nullptr;
HeadersWidget *headersDock = nullptr;
TypesWidget *typesDock = nullptr; TypesWidget *typesDock = nullptr;
SearchWidget *searchDock = nullptr; SearchWidget *searchDock = nullptr;
SymbolsWidget *symbolsDock = nullptr; SymbolsWidget *symbolsDock = nullptr;

View File

@ -250,6 +250,7 @@ border-top: 0px;
<addaction name="actionStrings"/> <addaction name="actionStrings"/>
<addaction name="actionFlags"/> <addaction name="actionFlags"/>
<addaction name="actionSections"/> <addaction name="actionSections"/>
<addaction name="actionHeaders"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionComments"/> <addaction name="actionComments"/>
<addaction name="actionConsole"/> <addaction name="actionConsole"/>
@ -1061,6 +1062,17 @@ background-color: palette(dark);
<string>Show/Hide Search panel</string> <string>Show/Hide Search panel</string>
</property> </property>
</action> </action>
<action name="actionHeaders">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Headers</string>
</property>
<property name="toolTip">
<string>Show/Hide Headers panel</string>
</property>
</action>
<action name="actionJupyter"> <action name="actionJupyter">
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>

View File

@ -0,0 +1,146 @@
#include "HeadersWidget.h"
#include "ui_HeadersWidget.h"
#include "MainWindow.h"
#include "utils/Helpers.h"
HeadersModel::HeadersModel(QList<HeaderDescription> *headers, QObject *parent)
: QAbstractListModel(parent),
headers(headers)
{
}
int HeadersModel::rowCount(const QModelIndex &) const
{
return headers->count();
}
int HeadersModel::columnCount(const QModelIndex &) const
{
return HeadersModel::ColumnCount;
}
QVariant HeadersModel::data(const QModelIndex &index, int role) const
{
if (index.row() >= headers->count())
return QVariant();
const HeaderDescription &header = headers->at(index.row());
switch (role) {
case Qt::DisplayRole:
switch (index.column()) {
case OffsetColumn:
return RAddressString(header.vaddr);
case NameColumn:
return header.name;
case ValueColumn:
return header.value;
default:
return QVariant();
}
case HeaderDescriptionRole:
return QVariant::fromValue(header);
default:
return QVariant();
}
}
QVariant HeadersModel::headerData(int section, Qt::Orientation, int role) const
{
switch (role) {
case Qt::DisplayRole:
switch (section) {
case OffsetColumn:
return tr("Offset");
case NameColumn:
return tr("Name");
case ValueColumn:
return tr("Value");
default:
return QVariant();
}
default:
return QVariant();
}
}
void HeadersModel::beginReloadHeaders()
{
beginResetModel();
}
void HeadersModel::endReloadHeaders()
{
endResetModel();
}
HeadersProxyModel::HeadersProxyModel(HeadersModel *sourceModel, QObject *parent)
: QSortFilterProxyModel(parent)
{
setSourceModel(sourceModel);
}
bool HeadersProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
{
QModelIndex index = sourceModel()->index(row, 0, parent);
HeaderDescription item = index.data(HeadersModel::HeaderDescriptionRole).value<HeaderDescription>();
return item.name.contains(filterRegExp());
}
bool HeadersProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
HeaderDescription leftHeader = left.data(HeadersModel::HeaderDescriptionRole).value<HeaderDescription>();
HeaderDescription rightHeader = right.data(HeadersModel::HeaderDescriptionRole).value<HeaderDescription>();
switch (left.column()) {
case HeadersModel::OffsetColumn:
return leftHeader.vaddr < rightHeader.vaddr;
case HeadersModel::NameColumn:
return leftHeader.name < rightHeader.name;
case HeadersModel::ValueColumn:
return leftHeader.value < rightHeader.value;
default:
break;
}
return leftHeader.vaddr < rightHeader.vaddr;
}
HeadersWidget::HeadersWidget(MainWindow *main, QAction *action) :
CutterDockWidget(main, action),
ui(new Ui::HeadersWidget)
{
ui->setupUi(this);
headersModel = new HeadersModel(&headers, this);
headersProxyModel = new HeadersProxyModel(headersModel, this);
ui->headersTreeView->setModel(headersProxyModel);
ui->headersTreeView->sortByColumn(HeadersModel::OffsetColumn, Qt::AscendingOrder);
setScrollMode();
connect(Core(), &CutterCore::refreshAll, this, &HeadersWidget::refreshHeaders);
}
HeadersWidget::~HeadersWidget() {}
void HeadersWidget::refreshHeaders()
{
headersModel->beginReloadHeaders();
headers = Core()->getAllHeaders();
headersModel->endReloadHeaders();
ui->headersTreeView->resizeColumnToContents(0);
ui->headersTreeView->resizeColumnToContents(1);
}
void HeadersWidget::setScrollMode()
{
qhelpers::setVerticalScrollMode(ui->headersTreeView);
}
void HeadersWidget::on_headersTreeView_doubleClicked(const QModelIndex &index)
{
HeaderDescription item = index.data(HeadersModel::HeaderDescriptionRole).value<HeaderDescription>();
Core()->seek(item.vaddr);
}

View File

@ -0,0 +1,88 @@
#ifndef HEADERSWIDGET_H
#define HEADERSWIDGET_H
#include <memory>
#include "Cutter.h"
#include "CutterDockWidget.h"
#include <QAbstractListModel>
#include <QSortFilterProxyModel>
class MainWindow;
class QTreeWidget;
namespace Ui
{
class HeadersWidget;
}
class MainWindow;
class QTreeWidgetItem;
class HeadersModel: public QAbstractListModel
{
Q_OBJECT
private:
QList<HeaderDescription> *headers;
public:
enum Column { OffsetColumn = 0, NameColumn, ValueColumn, ColumnCount };
enum Role { HeaderDescriptionRole = Qt::UserRole };
HeadersModel(QList<HeaderDescription> *headers, 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 beginReloadHeaders();
void endReloadHeaders();
};
class HeadersProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
HeadersProxyModel(HeadersModel *sourceModel, QObject *parent = nullptr);
protected:
bool filterAcceptsRow(int row, const QModelIndex &parent) const override;
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
};
class HeadersWidget : public CutterDockWidget
{
Q_OBJECT
public:
explicit HeadersWidget(MainWindow *main, QAction *action = nullptr);
~HeadersWidget();
private slots:
void on_headersTreeView_doubleClicked(const QModelIndex &index);
void refreshHeaders();
private:
std::unique_ptr<Ui::HeadersWidget> ui;
HeadersModel *headersModel;
HeadersProxyModel *headersProxyModel;
QList<HeaderDescription> headers;
void setScrollMode();
};
#endif // HEADERSWIDGET_H

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>HeadersWidget</class>
<widget class="QDockWidget" name="HeadersWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Headers</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="headersTreeView">
<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>