Add a panel for zignatures #463 (#505)

This commit is contained in:
rrreeezzz 2018-05-24 16:37:37 +01:00 committed by xarkes
parent cd776c24ef
commit b857e724e8
9 changed files with 382 additions and 3 deletions

View File

@ -1046,6 +1046,37 @@ QList<HeaderDescription> CutterCore::getAllHeaders()
return ret; return ret;
} }
QList<ZignatureDescription> CutterCore::getAllZignatures()
{
CORE_LOCK();
QList<ZignatureDescription> ret;
QJsonArray zignaturesArray = cmdj("zj").array();
for (QJsonValue value : zignaturesArray) {
QJsonObject zignatureObject = value.toObject();
ZignatureDescription zignature;
zignature.name = zignatureObject["name"].toString();
zignature.bytes = zignatureObject["bytes"].toString();
zignature.offset = zignatureObject["offset"].toVariant().toULongLong();
for (QJsonValue ref : zignatureObject["refs"].toArray()) {
zignature.refs << ref.toString();
}
QJsonObject graphObject = zignatureObject["graph"].toObject();
zignature.cc = graphObject["cc"].toVariant().toULongLong();
zignature.nbbs = graphObject["nbbs"].toVariant().toULongLong();
zignature.edges = graphObject["edges"].toVariant().toULongLong();
zignature.ebbs = graphObject["ebbs"].toVariant().toULongLong();
ret << zignature;
}
return ret;
}
QList<CommentDescription> CutterCore::getAllComments(const QString &filterType) QList<CommentDescription> CutterCore::getAllComments(const QString &filterType)
{ {
CORE_LOCK(); CORE_LOCK();

View File

@ -116,6 +116,18 @@ struct HeaderDescription
QString name; QString name;
}; };
struct ZignatureDescription
{
QString name;
QString bytes;
RVA cc;
RVA nbbs;
RVA edges;
RVA ebbs;
RVA offset;
QStringList refs;
};
struct TypeDescription { struct TypeDescription {
QString type; QString type;
int size; int size;
@ -284,6 +296,7 @@ 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(HeaderDescription)
Q_DECLARE_METATYPE(ZignatureDescription)
Q_DECLARE_METATYPE(SearchDescription) Q_DECLARE_METATYPE(SearchDescription)
Q_DECLARE_METATYPE(SectionDescription) Q_DECLARE_METATYPE(SectionDescription)
@ -439,6 +452,7 @@ public:
QList<ExportDescription> getAllExports(); QList<ExportDescription> getAllExports();
QList<SymbolDescription> getAllSymbols(); QList<SymbolDescription> getAllSymbols();
QList<HeaderDescription> getAllHeaders(); QList<HeaderDescription> getAllHeaders();
QList<ZignatureDescription> getAllZignatures();
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

@ -158,7 +158,8 @@ SOURCES += \
widgets/GraphWidget.cpp \ widgets/GraphWidget.cpp \
utils/JsonTreeItem.cpp \ utils/JsonTreeItem.cpp \
utils/JsonModel.cpp \ utils/JsonModel.cpp \
dialogs/VersionInfoDialog.cpp dialogs/VersionInfoDialog.cpp \
widgets/ZignaturesWidget.cpp
HEADERS += \ HEADERS += \
Cutter.h \ Cutter.h \
@ -231,7 +232,8 @@ HEADERS += \
widgets/GraphWidget.h \ widgets/GraphWidget.h \
utils/JsonTreeItem.h \ utils/JsonTreeItem.h \
utils/JsonModel.h \ utils/JsonModel.h \
dialogs/VersionInfoDialog.h dialogs/VersionInfoDialog.h \
widgets/ZignaturesWidget.h
FORMS += \ FORMS += \
dialogs/AboutDialog.ui \ dialogs/AboutDialog.ui \
@ -273,7 +275,8 @@ FORMS += \
widgets/SearchWidget.ui \ widgets/SearchWidget.ui \
widgets/JupyterWidget.ui \ widgets/JupyterWidget.ui \
dialogs/R2PluginsDialog.ui \ dialogs/R2PluginsDialog.ui \
dialogs/VersionInfoDialog.ui dialogs/VersionInfoDialog.ui \
widgets/ZignaturesWidget.ui
RESOURCES += \ RESOURCES += \
resources.qrc \ resources.qrc \

View File

@ -69,6 +69,7 @@
#include "widgets/VTablesWidget.h" #include "widgets/VTablesWidget.h"
#include "widgets/JupyterWidget.h" #include "widgets/JupyterWidget.h"
#include "widgets/HeadersWidget.h" #include "widgets/HeadersWidget.h"
#include "widgets/ZignaturesWidget.h"
// graphics // graphics
#include <QGraphicsEllipseItem> #include <QGraphicsEllipseItem>
@ -169,6 +170,7 @@ void MainWindow::initUI()
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); headersDock = new HeadersWidget(this, ui->actionHeaders);
zignaturesDock = new ZignaturesWidget(this, ui->actionZignatures);
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);
@ -464,6 +466,7 @@ void MainWindow::restoreDocks()
tabifyDockWidget(dashboardDock, typesDock); tabifyDockWidget(dashboardDock, typesDock);
tabifyDockWidget(dashboardDock, searchDock); tabifyDockWidget(dashboardDock, searchDock);
tabifyDockWidget(dashboardDock, headersDock); tabifyDockWidget(dashboardDock, headersDock);
tabifyDockWidget(dashboardDock, zignaturesDock);
tabifyDockWidget(dashboardDock, symbolsDock); tabifyDockWidget(dashboardDock, symbolsDock);
tabifyDockWidget(dashboardDock, classesDock); tabifyDockWidget(dashboardDock, classesDock);
tabifyDockWidget(dashboardDock, resourcesDock); tabifyDockWidget(dashboardDock, resourcesDock);

View File

@ -41,6 +41,7 @@ class ResourcesWidget;
class VTablesWidget; class VTablesWidget;
class TypesWidget; class TypesWidget;
class HeadersWidget; class HeadersWidget;
class ZignaturesWidget;
class SearchWidget; class SearchWidget;
#ifdef CUTTER_ENABLE_JUPYTER #ifdef CUTTER_ENABLE_JUPYTER
class JupyterWidget; class JupyterWidget;
@ -196,6 +197,7 @@ private:
QLineEdit *gotoEntry = nullptr; QLineEdit *gotoEntry = nullptr;
SdbDock *sdbDock = nullptr; SdbDock *sdbDock = nullptr;
SectionsWidget *sectionsDock = nullptr; SectionsWidget *sectionsDock = nullptr;
ZignaturesWidget *zignaturesDock = nullptr;
ConsoleWidget *consoleDock = nullptr; ConsoleWidget *consoleDock = nullptr;
ClassesWidget *classesDock = nullptr; ClassesWidget *classesDock = nullptr;
ResourcesWidget *resourcesDock = nullptr; ResourcesWidget *resourcesDock = nullptr;

View File

@ -251,6 +251,7 @@ border-top: 0px;
<addaction name="actionFlags"/> <addaction name="actionFlags"/>
<addaction name="actionSections"/> <addaction name="actionSections"/>
<addaction name="actionHeaders"/> <addaction name="actionHeaders"/>
<addaction name="actionZignatures"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionComments"/> <addaction name="actionComments"/>
<addaction name="actionConsole"/> <addaction name="actionConsole"/>
@ -1073,6 +1074,17 @@ background-color: palette(dark);
<string>Show/Hide Headers panel</string> <string>Show/Hide Headers panel</string>
</property> </property>
</action> </action>
<action name="actionZignatures">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Zignatures</string>
</property>
<property name="toolTip">
<string>Show/Hide Zignatures 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,161 @@
#include "ZignaturesWidget.h"
#include "ui_ZignaturesWidget.h"
#include "MainWindow.h"
#include "utils/Helpers.h"
ZignaturesModel::ZignaturesModel(QList<ZignatureDescription> *zignatures, QObject *parent)
: QAbstractListModel(parent),
zignatures(zignatures)
{
}
int ZignaturesModel::rowCount(const QModelIndex &) const
{
return zignatures->count();
}
int ZignaturesModel::columnCount(const QModelIndex &) const
{
return ZignaturesModel::ColumnCount;
}
QVariant ZignaturesModel::data(const QModelIndex &index, int role) const
{
if (index.row() >= zignatures->count())
return QVariant();
const ZignatureDescription &zignature = zignatures->at(index.row());
switch (role) {
case Qt::DisplayRole:
switch (index.column()) {
case OffsetColumn:
return RAddressString(zignature.offset);
case NameColumn:
return zignature.name;
case ValueColumn:
return zignature.bytes;
default:
return QVariant();
}
case ZignatureDescriptionRole:
return QVariant::fromValue(zignature);
case Qt::ToolTipRole: {
QString tmp = QString("Graph:\n\n Cyclomatic complexity: " + RSizeString(zignature.cc) +
"\n Nodes / basicblocks: " + RSizeString(zignature.nbbs) +
"\n Edges: " + RSizeString(zignature.edges) +
"\n Ebbs: " + RSizeString(zignature.ebbs) +
"\n\nRefs:\n");
for (QString ref : zignature.refs) {
tmp.append("\n " + ref);
}
return tmp;
}
default:
return QVariant();
}
}
QVariant ZignaturesModel::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("Bytes");
default:
return QVariant();
}
default:
return QVariant();
}
}
void ZignaturesModel::beginReloadZignatures()
{
beginResetModel();
}
void ZignaturesModel::endReloadZignatures()
{
endResetModel();
}
ZignaturesProxyModel::ZignaturesProxyModel(ZignaturesModel *sourceModel, QObject *parent)
: QSortFilterProxyModel(parent)
{
setSourceModel(sourceModel);
}
bool ZignaturesProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
{
QModelIndex index = sourceModel()->index(row, 0, parent);
ZignatureDescription item = index.data(ZignaturesModel::ZignatureDescriptionRole).value<ZignatureDescription>();
return item.name.contains(filterRegExp());
}
bool ZignaturesProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
ZignatureDescription leftZignature = left.data(ZignaturesModel::ZignatureDescriptionRole).value<ZignatureDescription>();
ZignatureDescription rightZignature = right.data(ZignaturesModel::ZignatureDescriptionRole).value<ZignatureDescription>();
switch (left.column()) {
case ZignaturesModel::OffsetColumn:
return leftZignature.offset < rightZignature.offset;
case ZignaturesModel::NameColumn:
return leftZignature.name < rightZignature.name;
case ZignaturesModel::ValueColumn:
return leftZignature.bytes < rightZignature.bytes;
default:
break;
}
return leftZignature.offset < rightZignature.offset;
}
ZignaturesWidget::ZignaturesWidget(MainWindow *main, QAction *action) :
CutterDockWidget(main, action),
ui(new Ui::ZignaturesWidget)
{
ui->setupUi(this);
zignaturesModel = new ZignaturesModel(&zignatures, this);
zignaturesProxyModel = new ZignaturesProxyModel(zignaturesModel, this);
ui->zignaturesTreeView->setModel(zignaturesProxyModel);
ui->zignaturesTreeView->sortByColumn(ZignaturesModel::OffsetColumn, Qt::AscendingOrder);
setScrollMode();
connect(Core(), &CutterCore::refreshAll, this, &ZignaturesWidget::refreshZignatures);
}
ZignaturesWidget::~ZignaturesWidget() {}
void ZignaturesWidget::refreshZignatures()
{
zignaturesModel->beginReloadZignatures();
zignatures = Core()->getAllZignatures();
zignaturesModel->endReloadZignatures();
ui->zignaturesTreeView->resizeColumnToContents(0);
ui->zignaturesTreeView->resizeColumnToContents(1);
ui->zignaturesTreeView->resizeColumnToContents(2);
}
void ZignaturesWidget::setScrollMode()
{
qhelpers::setVerticalScrollMode(ui->zignaturesTreeView);
}
void ZignaturesWidget::on_zignaturesTreeView_doubleClicked(const QModelIndex &index)
{
ZignatureDescription item = index.data(ZignaturesModel::ZignatureDescriptionRole).value<ZignatureDescription>();
Core()->seek(item.offset);
}

View File

@ -0,0 +1,83 @@
#ifndef ZIGNATURESWIDGET_H
#define ZIGNATURESWIDGET_H
#include <memory>
#include "Cutter.h"
#include "CutterDockWidget.h"
#include <QAbstractListModel>
#include <QSortFilterProxyModel>
class MainWindow;
class QTreeWidget;
class QTreeWidgetItem;
namespace Ui
{
class ZignaturesWidget;
}
class ZignaturesModel : public QAbstractListModel
{
Q_OBJECT
public:
enum Column { OffsetColumn = 0, NameColumn, ValueColumn, ColumnCount };
enum Role { ZignatureDescriptionRole = Qt::UserRole };
ZignaturesModel(QList<ZignatureDescription> *zignatures, QObject *parent = 0);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
void beginReloadZignatures();
void endReloadZignatures();
private:
QList<ZignatureDescription> *zignatures;
};
class ZignaturesProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
ZignaturesProxyModel(ZignaturesModel *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 ZignaturesWidget : public CutterDockWidget
{
Q_OBJECT
public:
explicit ZignaturesWidget(MainWindow *main, QAction *action = nullptr);
~ZignaturesWidget();
private slots:
void on_zignaturesTreeView_doubleClicked(const QModelIndex &index);
void refreshZignatures();
private:
std::unique_ptr<Ui::ZignaturesWidget> ui;
ZignaturesModel *zignaturesModel;
ZignaturesProxyModel *zignaturesProxyModel;
QList<ZignatureDescription> zignatures;
void setScrollMode();
};
#endif // ZIGNATURESWIDGET_H

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ZignaturesWidget</class>
<widget class="QDockWidget" name="ZignaturesWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Zignatures</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="zignaturesTreeView">
<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="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="autoScroll">
<bool>true</bool>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="indentation">
<number>8</number>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>