mirror of
https://github.com/rizinorg/cutter.git
synced 2025-02-07 15:32:13 +00:00
Added new graph view (WIP)
* This known unstable just a PoC
This commit is contained in:
parent
97ee9f17b6
commit
25a4d06697
@ -18,7 +18,7 @@ QT += core gui widgets webengine webenginewidgets
|
|||||||
|
|
||||||
QT_CONFIG -= no-pkg-config
|
QT_CONFIG -= no-pkg-config
|
||||||
|
|
||||||
CONFIG += c++11
|
CONFIG += debug c++11
|
||||||
|
|
||||||
# Define the preprocessor macro to get the application version in our application.
|
# Define the preprocessor macro to get the application version in our application.
|
||||||
DEFINES += APP_VERSION=\\\"$$VERSION\\\"
|
DEFINES += APP_VERSION=\\\"$$VERSION\\\"
|
||||||
@ -56,7 +56,6 @@ SOURCES += \
|
|||||||
widgets/commentswidget.cpp \
|
widgets/commentswidget.cpp \
|
||||||
widgets/stringswidget.cpp \
|
widgets/stringswidget.cpp \
|
||||||
widgets/flagswidget.cpp \
|
widgets/flagswidget.cpp \
|
||||||
widgets/memorywidget.cpp \
|
|
||||||
widgets/exportswidget.cpp \
|
widgets/exportswidget.cpp \
|
||||||
widgets/sdbdock.cpp \
|
widgets/sdbdock.cpp \
|
||||||
analthread.cpp \
|
analthread.cpp \
|
||||||
@ -71,7 +70,10 @@ SOURCES += \
|
|||||||
widgets/consolewidget.cpp \
|
widgets/consolewidget.cpp \
|
||||||
radarewebserver.cpp \
|
radarewebserver.cpp \
|
||||||
widgets/entrypointwidget.cpp \
|
widgets/entrypointwidget.cpp \
|
||||||
dialogs/flagdialog.cpp
|
dialogs/flagdialog.cpp \
|
||||||
|
widgets/DisassemblerGraphView.cpp \
|
||||||
|
widgets/MemoryWidget.cpp \
|
||||||
|
utils/RichTextPainter.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
mainwindow.h \
|
mainwindow.h \
|
||||||
@ -94,7 +96,6 @@ HEADERS += \
|
|||||||
widgets/commentswidget.h \
|
widgets/commentswidget.h \
|
||||||
widgets/stringswidget.h \
|
widgets/stringswidget.h \
|
||||||
widgets/flagswidget.h \
|
widgets/flagswidget.h \
|
||||||
widgets/memorywidget.h \
|
|
||||||
widgets/exportswidget.h \
|
widgets/exportswidget.h \
|
||||||
widgets/sdbdock.h \
|
widgets/sdbdock.h \
|
||||||
analthread.h \
|
analthread.h \
|
||||||
@ -112,7 +113,11 @@ HEADERS += \
|
|||||||
settings.h \
|
settings.h \
|
||||||
widgets/entrypointwidget.h \
|
widgets/entrypointwidget.h \
|
||||||
cutter.h \
|
cutter.h \
|
||||||
dialogs/flagdialog.h
|
dialogs/flagdialog.h \
|
||||||
|
widgets/DisassemblerGraphView.h \
|
||||||
|
widgets/MemoryWidget.h \
|
||||||
|
utils/RichTextPainter.h \
|
||||||
|
utils/CachedFontMetrics.h
|
||||||
FORMS += \
|
FORMS += \
|
||||||
mainwindow.ui \
|
mainwindow.ui \
|
||||||
newfiledialog.ui \
|
newfiledialog.ui \
|
||||||
@ -128,7 +133,6 @@ FORMS += \
|
|||||||
widgets/commentswidget.ui \
|
widgets/commentswidget.ui \
|
||||||
widgets/stringswidget.ui \
|
widgets/stringswidget.ui \
|
||||||
widgets/flagswidget.ui \
|
widgets/flagswidget.ui \
|
||||||
widgets/memorywidget.ui \
|
|
||||||
widgets/exportswidget.ui \
|
widgets/exportswidget.ui \
|
||||||
widgets/sdbdock.ui \
|
widgets/sdbdock.ui \
|
||||||
dialogs/commentsdialog.ui \
|
dialogs/commentsdialog.ui \
|
||||||
@ -138,7 +142,8 @@ FORMS += \
|
|||||||
widgets/sectionsdock.ui \
|
widgets/sectionsdock.ui \
|
||||||
widgets/consolewidget.ui \
|
widgets/consolewidget.ui \
|
||||||
widgets/entrypointwidget.ui \
|
widgets/entrypointwidget.ui \
|
||||||
dialogs/flagdialog.ui
|
dialogs/flagdialog.ui \
|
||||||
|
widgets/MemoryWidget.ui
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
resources.qrc
|
resources.qrc
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
#include "newfiledialog.h"
|
#include "newfiledialog.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
#include "widgets/memorywidget.h"
|
#include "widgets/MemoryWidget.h"
|
||||||
#include "widgets/functionswidget.h"
|
#include "widgets/functionswidget.h"
|
||||||
#include "widgets/sectionswidget.h"
|
#include "widgets/sectionswidget.h"
|
||||||
#include "widgets/commentswidget.h"
|
#include "widgets/commentswidget.h"
|
||||||
@ -60,6 +60,7 @@
|
|||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "optionsdialog.h"
|
#include "optionsdialog.h"
|
||||||
#include "widgets/entrypointwidget.h"
|
#include "widgets/entrypointwidget.h"
|
||||||
|
#include "widgets/DisassemblerGraphView.h"
|
||||||
|
|
||||||
// graphics
|
// graphics
|
||||||
#include <QGraphicsEllipseItem>
|
#include <QGraphicsEllipseItem>
|
||||||
@ -204,7 +205,7 @@ void MainWindow::initUI()
|
|||||||
/*
|
/*
|
||||||
* Dock Widgets
|
* Dock Widgets
|
||||||
*/
|
*/
|
||||||
dockWidgets.reserve(11);
|
dockWidgets.reserve(12);
|
||||||
|
|
||||||
// Add Memory DockWidget
|
// Add Memory DockWidget
|
||||||
this->memoryDock = new MemoryWidget(this);
|
this->memoryDock = new MemoryWidget(this);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
// TODO: remove us
|
// TODO: remove us
|
||||||
#include "widgets/memorywidget.h"
|
#include "widgets/MemoryWidget.h"
|
||||||
#include "widgets/notepad.h"
|
#include "widgets/notepad.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
|
63
src/utils/CachedFontMetrics.h
Normal file
63
src/utils/CachedFontMetrics.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#ifndef CACHEDFONTMETRICS_H
|
||||||
|
#define CACHEDFONTMETRICS_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QFont>
|
||||||
|
#include <QFontMetrics>
|
||||||
|
|
||||||
|
class CachedFontMetrics : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit CachedFontMetrics(QObject* parent, const QFont & font)
|
||||||
|
: QObject(parent),
|
||||||
|
mFontMetrics(font)
|
||||||
|
{
|
||||||
|
memset(mWidths, 0, sizeof(mWidths));
|
||||||
|
mHeight = mFontMetrics.height();
|
||||||
|
}
|
||||||
|
|
||||||
|
int width(const QChar & ch)
|
||||||
|
{
|
||||||
|
auto unicode = ch.unicode();
|
||||||
|
if(unicode >= 0xD800)
|
||||||
|
{
|
||||||
|
if(unicode >= 0xE000)
|
||||||
|
unicode -= 0xE000 - 0xD800;
|
||||||
|
else
|
||||||
|
// is lonely surrogate
|
||||||
|
return mFontMetrics.width(ch);
|
||||||
|
}
|
||||||
|
if(!mWidths[unicode])
|
||||||
|
return mWidths[unicode] = mFontMetrics.width(ch);
|
||||||
|
return mWidths[unicode];
|
||||||
|
}
|
||||||
|
|
||||||
|
int width(const QString & text)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
QChar temp;
|
||||||
|
for(const QChar & ch : text)
|
||||||
|
{
|
||||||
|
if(ch.isHighSurrogate())
|
||||||
|
temp = ch;
|
||||||
|
else if(ch.isLowSurrogate())
|
||||||
|
result += mFontMetrics.width(QString(temp) + ch);
|
||||||
|
else
|
||||||
|
result += width(ch);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int height()
|
||||||
|
{
|
||||||
|
return mHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QFontMetrics mFontMetrics;
|
||||||
|
uchar mWidths[0x10000 - 0xE000 + 0xD800];
|
||||||
|
int mHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CACHEDFONTMETRICS_H
|
103
src/utils/RichTextPainter.cpp
Normal file
103
src/utils/RichTextPainter.cpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/* x64dbg RichTextPainter */
|
||||||
|
#include "RichTextPainter.h"
|
||||||
|
#include "CachedFontMetrics.h"
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
//TODO: fix performance (possibly use QTextLayout?)
|
||||||
|
void RichTextPainter::paintRichText(QPainter* painter, int x, int y, int w, int h, int xinc, const List & richText, CachedFontMetrics* fontMetrics)
|
||||||
|
{
|
||||||
|
QPen pen;
|
||||||
|
QPen highlightPen;
|
||||||
|
QBrush brush(Qt::cyan);
|
||||||
|
for(const CustomRichText_t & curRichText : richText)
|
||||||
|
{
|
||||||
|
int textWidth = fontMetrics->width(curRichText.text);
|
||||||
|
int backgroundWidth = textWidth;
|
||||||
|
if(backgroundWidth + xinc > w)
|
||||||
|
backgroundWidth = w - xinc;
|
||||||
|
if(backgroundWidth <= 0) //stop drawing when going outside the specified width
|
||||||
|
break;
|
||||||
|
switch(curRichText.flags)
|
||||||
|
{
|
||||||
|
case FlagNone: //defaults
|
||||||
|
break;
|
||||||
|
case FlagColor: //color only
|
||||||
|
pen.setColor(curRichText.textColor);
|
||||||
|
painter->setPen(pen);
|
||||||
|
break;
|
||||||
|
case FlagBackground: //background only
|
||||||
|
if(backgroundWidth > 0 && curRichText.textBackground.alpha())
|
||||||
|
{
|
||||||
|
brush.setColor(curRichText.textBackground);
|
||||||
|
painter->fillRect(QRect(x + xinc, y, backgroundWidth, h), brush);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FlagAll: //color+background
|
||||||
|
if(backgroundWidth > 0 && curRichText.textBackground.alpha())
|
||||||
|
{
|
||||||
|
brush.setColor(curRichText.textBackground);
|
||||||
|
painter->fillRect(QRect(x + xinc, y, backgroundWidth, h), brush);
|
||||||
|
}
|
||||||
|
pen.setColor(curRichText.textColor);
|
||||||
|
painter->setPen(pen);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
painter->drawText(QRect(x + xinc, y, w - xinc, h), Qt::TextBypassShaping, curRichText.text);
|
||||||
|
if(curRichText.highlight && curRichText.highlightColor.alpha())
|
||||||
|
{
|
||||||
|
highlightPen.setColor(curRichText.highlightColor);
|
||||||
|
highlightPen.setWidth(curRichText.highlightWidth);
|
||||||
|
painter->setPen(highlightPen);
|
||||||
|
int highlightOffsetX = curRichText.highlightConnectPrev ? -1 : 1;
|
||||||
|
painter->drawLine(x + xinc + highlightOffsetX, y + h - 1, x + xinc + backgroundWidth - 1, y + h - 1);
|
||||||
|
}
|
||||||
|
xinc += textWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief RichTextPainter::htmlRichText Convert rich text in x64dbg to HTML, for use by other applications
|
||||||
|
* @param richText The rich text to be converted to HTML format
|
||||||
|
* @param textHtml The HTML source. Any previous content will be preserved and new content will be appended at the end.
|
||||||
|
* @param textPlain The plain text. Any previous content will be preserved and new content will be appended at the end.
|
||||||
|
*/
|
||||||
|
void RichTextPainter::htmlRichText(const List & richText, QString & textHtml, QString & textPlain)
|
||||||
|
{
|
||||||
|
for(const CustomRichText_t & curRichText : richText)
|
||||||
|
{
|
||||||
|
if(curRichText.text == " ") //blank
|
||||||
|
{
|
||||||
|
textHtml += " ";
|
||||||
|
textPlain += " ";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch(curRichText.flags)
|
||||||
|
{
|
||||||
|
case FlagNone: //defaults
|
||||||
|
textHtml += "<span>";
|
||||||
|
break;
|
||||||
|
case FlagColor: //color only
|
||||||
|
textHtml += QString("<span style=\"color:%1\">").arg(curRichText.textColor.name());
|
||||||
|
break;
|
||||||
|
case FlagBackground: //background only
|
||||||
|
if(curRichText.textBackground != Qt::transparent) // QColor::name() returns "#000000" for transparent color. That's not desired. Leave it blank.
|
||||||
|
textHtml += QString("<span style=\"background-color:%1\">").arg(curRichText.textBackground.name());
|
||||||
|
else
|
||||||
|
textHtml += QString("<span>");
|
||||||
|
break;
|
||||||
|
case FlagAll: //color+background
|
||||||
|
if(curRichText.textBackground != Qt::transparent) // QColor::name() returns "#000000" for transparent color. That's not desired. Leave it blank.
|
||||||
|
textHtml += QString("<span style=\"color:%1; background-color:%2\">").arg(curRichText.textColor.name(), curRichText.textBackground.name());
|
||||||
|
else
|
||||||
|
textHtml += QString("<span style=\"color:%1\">").arg(curRichText.textColor.name());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(curRichText.highlight) //Underline highlighted token
|
||||||
|
textHtml += "<u>";
|
||||||
|
textHtml += curRichText.text.toHtmlEscaped();
|
||||||
|
if(curRichText.highlight)
|
||||||
|
textHtml += "</u>";
|
||||||
|
textHtml += "</span>"; //Close the tag
|
||||||
|
textPlain += curRichText.text;
|
||||||
|
}
|
||||||
|
}
|
43
src/utils/RichTextPainter.h
Normal file
43
src/utils/RichTextPainter.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/* x64dbg RichTextPainter */
|
||||||
|
#ifndef RICHTEXTPAINTER_H
|
||||||
|
#define RICHTEXTPAINTER_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QColor>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class CachedFontMetrics;
|
||||||
|
class QPainter;
|
||||||
|
|
||||||
|
class RichTextPainter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//structures
|
||||||
|
enum CustomRichTextFlags
|
||||||
|
{
|
||||||
|
FlagNone,
|
||||||
|
FlagColor,
|
||||||
|
FlagBackground,
|
||||||
|
FlagAll
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CustomRichText_t
|
||||||
|
{
|
||||||
|
QString text;
|
||||||
|
QColor textColor;
|
||||||
|
QColor textBackground;
|
||||||
|
CustomRichTextFlags flags;
|
||||||
|
bool highlight;
|
||||||
|
QColor highlightColor;
|
||||||
|
int highlightWidth = 2;
|
||||||
|
bool highlightConnectPrev = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<CustomRichText_t> List;
|
||||||
|
|
||||||
|
//functions
|
||||||
|
static void paintRichText(QPainter* painter, int x, int y, int w, int h, int xinc, const List & richText, CachedFontMetrics* fontMetrics);
|
||||||
|
static void htmlRichText(const List & richText, QString & textHtml, QString & textPlain);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // RICHTEXTPAINTER_H
|
2142
src/widgets/DisassemblerGraphView.cpp
Normal file
2142
src/widgets/DisassemblerGraphView.cpp
Normal file
File diff suppressed because it is too large
Load Diff
363
src/widgets/DisassemblerGraphView.h
Normal file
363
src/widgets/DisassemblerGraphView.h
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
/* x64dbg DisassemblerGraphView */
|
||||||
|
#ifndef DISASSEMBLERGRAPHVIEW_H
|
||||||
|
#define DISASSEMBLERGRAPHVIEW_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QAbstractScrollArea>
|
||||||
|
#include <QPaintEvent>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QSize>
|
||||||
|
#include <QResizeEvent>
|
||||||
|
#include <tuple>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <queue>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include "cutter.h"
|
||||||
|
#include "utils/RichTextPainter.h"
|
||||||
|
#include "utils/CachedFontMetrics.h"
|
||||||
|
|
||||||
|
#define duint ut64
|
||||||
|
|
||||||
|
class MenuBuilder;
|
||||||
|
class CachedFontMetrics;
|
||||||
|
class GotoDialog;
|
||||||
|
class XrefBrowseDialog;
|
||||||
|
|
||||||
|
class DisassemblerGraphView : public QAbstractScrollArea
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
struct DisassemblerBlock;
|
||||||
|
|
||||||
|
struct Point
|
||||||
|
{
|
||||||
|
int row; //point[0]
|
||||||
|
int col; //point[1]
|
||||||
|
int index; //point[2]
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DisassemblerEdge
|
||||||
|
{
|
||||||
|
QColor color;
|
||||||
|
DisassemblerBlock* dest;
|
||||||
|
std::vector<Point> points;
|
||||||
|
int start_index = 0;
|
||||||
|
|
||||||
|
QPolygonF polyline;
|
||||||
|
QPolygonF arrow;
|
||||||
|
|
||||||
|
void addPoint(int row, int col, int index = 0)
|
||||||
|
{
|
||||||
|
Point point = {row, col, 0};
|
||||||
|
this->points.push_back(point);
|
||||||
|
if(int(this->points.size()) > 1)
|
||||||
|
this->points[this->points.size() - 2].index = index;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Token
|
||||||
|
{
|
||||||
|
int start; //token[0]
|
||||||
|
int length; //token[1]
|
||||||
|
QString type; //token[2]
|
||||||
|
duint addr; //token[3]
|
||||||
|
QString name; //token[4]
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HighlightToken
|
||||||
|
{
|
||||||
|
QString type; //highlight_token[0]
|
||||||
|
duint addr; //highlight_token[1]
|
||||||
|
QString name; //highlight_token[2]
|
||||||
|
|
||||||
|
bool equalsToken(const Token & token)
|
||||||
|
{
|
||||||
|
return this->type == token.type &&
|
||||||
|
this->addr == token.addr &&
|
||||||
|
this->name == token.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HighlightToken* fromToken(const Token & token)
|
||||||
|
{
|
||||||
|
//TODO: memory leaks
|
||||||
|
auto result = new HighlightToken();
|
||||||
|
result->type = token.type;
|
||||||
|
result->addr = token.addr;
|
||||||
|
result->name = token.name;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Text
|
||||||
|
{
|
||||||
|
std::vector<RichTextPainter::List> lines;
|
||||||
|
|
||||||
|
Text() {}
|
||||||
|
|
||||||
|
Text(const QString & text, QColor color, QColor background)
|
||||||
|
{
|
||||||
|
RichTextPainter::List richText;
|
||||||
|
RichTextPainter::CustomRichText_t rt;
|
||||||
|
rt.highlight = false;
|
||||||
|
rt.text = text;
|
||||||
|
rt.textColor = color;
|
||||||
|
rt.textBackground = background;
|
||||||
|
rt.flags = rt.textBackground.alpha() ? RichTextPainter::FlagAll : RichTextPainter::FlagColor;
|
||||||
|
richText.push_back(rt);
|
||||||
|
lines.push_back(richText);
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(const RichTextPainter::List & richText)
|
||||||
|
{
|
||||||
|
lines.push_back(richText);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ToQString() const
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
for(auto & line : lines)
|
||||||
|
{
|
||||||
|
for(auto & t : line)
|
||||||
|
{
|
||||||
|
result += t.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::move(result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Instr
|
||||||
|
{
|
||||||
|
duint addr = 0;
|
||||||
|
Text text;
|
||||||
|
std::vector<unsigned char> opcode; //instruction bytes
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Block
|
||||||
|
{
|
||||||
|
Text header_text;
|
||||||
|
std::vector<Instr> instrs;
|
||||||
|
std::vector<duint> exits;
|
||||||
|
duint entry = 0;
|
||||||
|
duint true_path = 0;
|
||||||
|
duint false_path = 0;
|
||||||
|
bool terminal = false;
|
||||||
|
bool indirectcall = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DisassemblerBlock
|
||||||
|
{
|
||||||
|
DisassemblerBlock() {}
|
||||||
|
explicit DisassemblerBlock(Block & block)
|
||||||
|
: block(block) {}
|
||||||
|
|
||||||
|
Block block;
|
||||||
|
std::vector<DisassemblerEdge> edges;
|
||||||
|
std::vector<duint> incoming;
|
||||||
|
std::vector<duint> new_exits;
|
||||||
|
|
||||||
|
qreal x = 0.0;
|
||||||
|
qreal y = 0.0;
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
int col = 0;
|
||||||
|
int col_count = 0;
|
||||||
|
int row = 0;
|
||||||
|
int row_count = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Function
|
||||||
|
{
|
||||||
|
bool ready;
|
||||||
|
duint entry;
|
||||||
|
duint update_id;
|
||||||
|
std::vector<Block> blocks;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Analysis
|
||||||
|
{
|
||||||
|
duint entry = 0;
|
||||||
|
std::unordered_map<duint, Function> functions;
|
||||||
|
bool ready = false;
|
||||||
|
duint update_id = 0;
|
||||||
|
QString status = "Analyzing...";
|
||||||
|
|
||||||
|
bool find_instr(duint addr, duint & func, duint & instr)
|
||||||
|
{
|
||||||
|
//TODO implement
|
||||||
|
Q_UNUSED(addr);
|
||||||
|
Q_UNUSED(func);
|
||||||
|
Q_UNUSED(instr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//dummy class
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class LayoutType
|
||||||
|
{
|
||||||
|
Wide,
|
||||||
|
Medium,
|
||||||
|
Narrow,
|
||||||
|
};
|
||||||
|
|
||||||
|
DisassemblerGraphView(QWidget *parent, CutterCore *core);
|
||||||
|
~DisassemblerGraphView();
|
||||||
|
void initFont();
|
||||||
|
void adjustSize(int width, int height);
|
||||||
|
void resizeEvent(QResizeEvent* event);
|
||||||
|
duint get_cursor_pos();
|
||||||
|
void set_cursor_pos(duint addr);
|
||||||
|
std::tuple<duint, duint> get_selection_range();
|
||||||
|
void set_selection_range(std::tuple<duint, duint> range);
|
||||||
|
void copy_address();
|
||||||
|
//void analysis_thread_proc();
|
||||||
|
//void closeRequest();
|
||||||
|
void paintNormal(QPainter & p, QRect & viewportRect, int xofs, int yofs);
|
||||||
|
void paintOverview(QPainter & p, QRect & viewportRect, int xofs, int yofs);
|
||||||
|
void paintEvent(QPaintEvent* event);
|
||||||
|
bool isMouseEventInBlock(QMouseEvent* event);
|
||||||
|
duint getInstrForMouseEvent(QMouseEvent* event);
|
||||||
|
bool getTokenForMouseEvent(QMouseEvent* event, Token & token);
|
||||||
|
bool find_instr(duint addr, Instr & instr);
|
||||||
|
void mousePressEvent(QMouseEvent* event);
|
||||||
|
void mouseMoveEvent(QMouseEvent* event);
|
||||||
|
void mouseReleaseEvent(QMouseEvent* event);
|
||||||
|
void mouseDoubleClickEvent(QMouseEvent* event);
|
||||||
|
void prepareGraphNode(DisassemblerBlock & block);
|
||||||
|
void adjustGraphLayout(DisassemblerBlock & block, int col, int row);
|
||||||
|
void computeGraphLayout(DisassemblerBlock & block);
|
||||||
|
void setupContextMenu();
|
||||||
|
void keyPressEvent(QKeyEvent* event);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using Matrix = std::vector<std::vector<T>>;
|
||||||
|
using EdgesVector = Matrix<std::vector<bool>>;
|
||||||
|
bool isEdgeMarked(EdgesVector & edges, int row, int col, int index);
|
||||||
|
void markEdge(EdgesVector & edges, int row, int col, int index, bool used = true);
|
||||||
|
int findHorizEdgeIndex(EdgesVector & edges, int row, int min_col, int max_col);
|
||||||
|
int findVertEdgeIndex(EdgesVector & edges, int col, int min_row, int max_row);
|
||||||
|
DisassemblerEdge routeEdge(EdgesVector & horiz_edges, EdgesVector & vert_edges, Matrix<bool> & edge_valid, DisassemblerBlock & start, DisassemblerBlock & end, QColor color);
|
||||||
|
void renderFunction(Function & func);
|
||||||
|
void show_cur_instr(bool force = false);
|
||||||
|
bool navigate(duint addr);
|
||||||
|
void fontChanged();
|
||||||
|
void setGraphLayout(LayoutType layout);
|
||||||
|
|
||||||
|
//VaHistory mHistory;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void displaySnowmanWidget();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void updateTimerEvent();
|
||||||
|
//void loadGraphSlot(BridgeCFGraphList* graph, duint addr);
|
||||||
|
void graphAtSlot(duint addr);
|
||||||
|
void updateGraphSlot();
|
||||||
|
void followDisassemblerSlot();
|
||||||
|
void colorsUpdatedSlot();
|
||||||
|
void fontsUpdatedSlot();
|
||||||
|
void shortcutsUpdatedSlot();
|
||||||
|
void toggleOverviewSlot();
|
||||||
|
void toggleSummarySlot();
|
||||||
|
//void selectionGetSlot(SELECTIONDATA* selection);
|
||||||
|
void tokenizerConfigUpdatedSlot();
|
||||||
|
void loadCurrentGraph();
|
||||||
|
//void disassembleAtSlot(dsint va, dsint cip);
|
||||||
|
void gotoExpressionSlot();
|
||||||
|
void gotoOriginSlot();
|
||||||
|
void gotoPreviousSlot();
|
||||||
|
void gotoNextSlot();
|
||||||
|
void toggleSyncOriginSlot();
|
||||||
|
void followActionSlot();
|
||||||
|
void refreshSlot();
|
||||||
|
void saveImageSlot();
|
||||||
|
void setCommentSlot();
|
||||||
|
void setLabelSlot();
|
||||||
|
void xrefSlot();
|
||||||
|
void decompileSlot();
|
||||||
|
|
||||||
|
private:
|
||||||
|
CutterCore *mCore;
|
||||||
|
QString status;
|
||||||
|
Analysis analysis;
|
||||||
|
duint function;
|
||||||
|
QTimer* updateTimer;
|
||||||
|
int baseline;
|
||||||
|
qreal charWidth;
|
||||||
|
int charHeight;
|
||||||
|
int charOffset;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int renderWidth;
|
||||||
|
int renderHeight;
|
||||||
|
int renderXOfs;
|
||||||
|
int renderYOfs;
|
||||||
|
duint cur_instr;
|
||||||
|
int scroll_base_x;
|
||||||
|
int scroll_base_y;
|
||||||
|
duint update_id;
|
||||||
|
bool scroll_mode;
|
||||||
|
bool ready;
|
||||||
|
int* desired_pos;
|
||||||
|
std::unordered_map<duint, DisassemblerBlock> blocks;
|
||||||
|
HighlightToken* highlight_token;
|
||||||
|
std::vector<int> col_edge_x;
|
||||||
|
std::vector<int> row_edge_y;
|
||||||
|
CachedFontMetrics* mFontMetrics;
|
||||||
|
MenuBuilder* mMenuBuilder;
|
||||||
|
bool drawOverview;
|
||||||
|
bool onlySummary;
|
||||||
|
bool syncOrigin;
|
||||||
|
int overviewXOfs;
|
||||||
|
int overviewYOfs;
|
||||||
|
qreal overviewScale;
|
||||||
|
duint mCip;
|
||||||
|
bool forceCenter;
|
||||||
|
bool saveGraph;
|
||||||
|
bool mHistoryLock; //Don't add a history while going to previous/next
|
||||||
|
LayoutType layoutType;
|
||||||
|
|
||||||
|
QAction* mToggleOverview;
|
||||||
|
QAction* mToggleSummary;
|
||||||
|
QAction* mToggleSyncOrigin;
|
||||||
|
|
||||||
|
QColor disassemblyBackgroundColor;
|
||||||
|
QColor disassemblySelectionColor;
|
||||||
|
QColor disassemblyTracedColor;
|
||||||
|
QColor disassemblyTracedSelectionColor;
|
||||||
|
QColor jmpColor;
|
||||||
|
QColor brtrueColor;
|
||||||
|
QColor brfalseColor;
|
||||||
|
QColor retShadowColor;
|
||||||
|
QColor indirectcallShadowColor;
|
||||||
|
QColor backgroundColor;
|
||||||
|
QColor mAutoCommentColor;
|
||||||
|
QColor mAutoCommentBackgroundColor;
|
||||||
|
QColor mCommentColor;
|
||||||
|
QColor mCommentBackgroundColor;
|
||||||
|
QColor mLabelColor;
|
||||||
|
QColor mLabelBackgroundColor;
|
||||||
|
QColor graphNodeColor;
|
||||||
|
QColor mAddressColor;
|
||||||
|
QColor mAddressBackgroundColor;
|
||||||
|
QColor mCipColor;
|
||||||
|
QColor mBreakpointColor;
|
||||||
|
QColor mDisabledBreakpointColor;
|
||||||
|
|
||||||
|
//BridgeCFGraph currentGraph;
|
||||||
|
std::unordered_map<duint, duint> currentBlockMap;
|
||||||
|
//QBeaEngine disasm;
|
||||||
|
GotoDialog* mGoto;
|
||||||
|
XrefBrowseDialog* mXrefDlg;
|
||||||
|
|
||||||
|
void addReferenceAction(QMenu* menu, duint addr);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DISASSEMBLERGRAPHVIEW_H
|
@ -1,5 +1,6 @@
|
|||||||
#include "memorywidget.h"
|
#include "MemoryWidget.h"
|
||||||
#include "ui_memorywidget.h"
|
#include "ui_MemoryWidget.h"
|
||||||
|
#include "DisassemblerGraphView.h"
|
||||||
|
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
@ -159,6 +160,11 @@ MemoryWidget::MemoryWidget(MainWindow *main) :
|
|||||||
connect(new QShortcut(Qt::SHIFT + Qt::Key_X, ui->disasTextEdit_2),
|
connect(new QShortcut(Qt::SHIFT + Qt::Key_X, ui->disasTextEdit_2),
|
||||||
SIGNAL(activated()), this, SLOT(showXrefsDialog()));
|
SIGNAL(activated()), this, SLOT(showXrefsDialog()));
|
||||||
|
|
||||||
|
// Create Graph View
|
||||||
|
ui->tabGraph->setLayout(new QGridLayout);
|
||||||
|
mGraphView = new DisassemblerGraphView(ui->tabGraph, main->core);
|
||||||
|
ui->tabGraph->layout()->addWidget(mGraphView);
|
||||||
|
|
||||||
// Space to switch between disassembly and graph
|
// Space to switch between disassembly and graph
|
||||||
QShortcut *graph_shortcut = new QShortcut(QKeySequence(Qt::Key_Space), this->main);
|
QShortcut *graph_shortcut = new QShortcut(QKeySequence(Qt::Key_Space), this->main);
|
||||||
connect(graph_shortcut, SIGNAL(activated()), this, SLOT(cycleViews()));
|
connect(graph_shortcut, SIGNAL(activated()), this, SLOT(cycleViews()));
|
||||||
@ -1136,7 +1142,7 @@ void MemoryWidget::on_actionSettings_menu_1_triggered()
|
|||||||
bool ok = true;
|
bool ok = true;
|
||||||
|
|
||||||
// QFont font = QFont("Monospace", 8);
|
// QFont font = QFont("Monospace", 8);
|
||||||
|
// TODO Use global configuration
|
||||||
QFont font = QFontDialog::getFont(&ok, ui->disasTextEdit_2->font(), this);
|
QFont font = QFontDialog::getFont(&ok, ui->disasTextEdit_2->font(), this);
|
||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
@ -1267,6 +1273,12 @@ void MemoryWidget::on_graphButton_2_clicked()
|
|||||||
ui->memSideTabWidget_2->setCurrentIndex(0);
|
ui->memSideTabWidget_2->setCurrentIndex(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MemoryWidget::on_graphButton_clicked()
|
||||||
|
{
|
||||||
|
ui->memTabWidget->setCurrentIndex(3);
|
||||||
|
ui->memSideTabWidget_2->setCurrentIndex(3);
|
||||||
|
}
|
||||||
|
|
||||||
void MemoryWidget::on_actionSend_to_Notepad_triggered()
|
void MemoryWidget::on_actionSend_to_Notepad_triggered()
|
||||||
{
|
{
|
||||||
QTextCursor cursor = ui->disasTextEdit_2->textCursor();
|
QTextCursor cursor = ui->disasTextEdit_2->textCursor();
|
@ -15,6 +15,7 @@
|
|||||||
#include "hexascii_highlighter.h"
|
#include "hexascii_highlighter.h"
|
||||||
#include "hexhighlighter.h"
|
#include "hexhighlighter.h"
|
||||||
#include "dashboard.h"
|
#include "dashboard.h"
|
||||||
|
#include "widgets/DisassemblerGraphView.h"
|
||||||
|
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
|
|
||||||
@ -46,6 +47,7 @@ public:
|
|||||||
QTabWidget *memTabWidget;
|
QTabWidget *memTabWidget;
|
||||||
QWebEngineView *graphWebView;
|
QWebEngineView *graphWebView;
|
||||||
QWebEngineView *histoWebView;
|
QWebEngineView *histoWebView;
|
||||||
|
DisassemblerGraphView *mGraphView;
|
||||||
|
|
||||||
Highlighter *highlighter;
|
Highlighter *highlighter;
|
||||||
Highlighter *highlighter_5;
|
Highlighter *highlighter_5;
|
||||||
@ -139,6 +141,7 @@ private slots:
|
|||||||
void on_disButton_2_clicked();
|
void on_disButton_2_clicked();
|
||||||
void on_hexButton_2_clicked();
|
void on_hexButton_2_clicked();
|
||||||
void on_graphButton_2_clicked();
|
void on_graphButton_2_clicked();
|
||||||
|
void on_graphButton_clicked();
|
||||||
void showDisasContextMenu(const QPoint &pt);
|
void showDisasContextMenu(const QPoint &pt);
|
||||||
void showHexdumpContextMenu(const QPoint &pt);
|
void showHexdumpContextMenu(const QPoint &pt);
|
||||||
void showHexASCIIContextMenu(const QPoint &pt);
|
void showHexASCIIContextMenu(const QPoint &pt);
|
@ -178,7 +178,7 @@ QToolTip {
|
|||||||
}</string>
|
}</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string>...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="../resources.qrc">
|
<iconset resource="../resources.qrc">
|
||||||
@ -255,6 +255,63 @@ QToolTip {
|
|||||||
</attribute>
|
</attribute>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="graphButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Graph</string>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QToolButton { /* all types of tool button */
|
||||||
|
border: 5px solid #333;
|
||||||
|
border-left: 10px solid #333;
|
||||||
|
border-right: 10px solid #333;
|
||||||
|
border-radius: 0px;
|
||||||
|
background-color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
QToolButton:hover {
|
||||||
|
border: 5px solid #444;
|
||||||
|
border-radius: 0px;
|
||||||
|
background-color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
QToolButton:checked {
|
||||||
|
border: 5px solid #2180a9;
|
||||||
|
border-radius: 0px;
|
||||||
|
background-color: #2180a9;
|
||||||
|
}
|
||||||
|
|
||||||
|
QToolTip {
|
||||||
|
background-color: #444;
|
||||||
|
border: 3px solid #444;
|
||||||
|
color: rgb(232, 232, 232);
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../resources.qrc">
|
||||||
|
<normaloff>:/img/icons/graph_light.svg</normaloff>
|
||||||
|
<normalon>:/img/icons/graph_white.svg</normalon>:/img/icons/graph_light.svg</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="buttonGroup">
|
||||||
|
<string notr="true">buttonGroup</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_6">
|
<spacer name="verticalSpacer_6">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@ -456,7 +513,7 @@ border-top: 0px;
|
|||||||
<enum>QTabWidget::South</enum>
|
<enum>QTabWidget::South</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="documentMode">
|
<property name="documentMode">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
@ -1249,6 +1306,12 @@ p, li { white-space: pre-wrap; }
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QWidget" name="tabGraph">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Page</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_19"/>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -3046,8 +3109,8 @@ QToolTip {
|
|||||||
</resources>
|
</resources>
|
||||||
<connections/>
|
<connections/>
|
||||||
<buttongroups>
|
<buttongroups>
|
||||||
<buttongroup name="buttonGroup_3"/>
|
|
||||||
<buttongroup name="buttonGroup_2"/>
|
<buttongroup name="buttonGroup_2"/>
|
||||||
|
<buttongroup name="buttonGroup_3"/>
|
||||||
<buttongroup name="buttonGroup"/>
|
<buttongroup name="buttonGroup"/>
|
||||||
</buttongroups>
|
</buttongroups>
|
||||||
</ui>
|
</ui>
|
Loading…
Reference in New Issue
Block a user