Added a BasicBlock highlighting API

This commit is contained in:
xarkes 2019-02-19 19:56:59 +01:00 committed by Florian Märkl
parent 7caabf5350
commit a93c5e225f
9 changed files with 120 additions and 31 deletions

View File

@ -167,6 +167,10 @@ CutterCore::CutterCore(QObject *parent) :
// Otherwise r2 may ask the user for input and Cutter would freeze // Otherwise r2 may ask the user for input and Cutter would freeze
setConfig("scr.interactive", false); setConfig("scr.interactive", false);
// Initialize graph node highlighter
bbHighlighter = new BasicBlockHighlighter();
// Initialize Async tasks manager
asyncTaskManager = new AsyncTaskManager(this); asyncTaskManager = new AsyncTaskManager(this);
} }
@ -231,6 +235,7 @@ bool CutterCore::sdbSet(QString path, QString key, QString val)
CutterCore::~CutterCore() CutterCore::~CutterCore()
{ {
delete bbHighlighter;
r_core_free(this->core_); r_core_free(this->core_);
r_cons_free(); r_cons_free();
} }
@ -2628,3 +2633,8 @@ QString CutterCore::ansiEscapeToHtml(const QString &text)
free(html); free(html);
return r; return r;
} }
BasicBlockHighlighter* CutterCore::getBBHighlighter()
{
return bbHighlighter;
}

View File

@ -46,6 +46,7 @@ typedef ut64 RVA;
class AsyncTaskManager; class AsyncTaskManager;
class CutterCore; class CutterCore;
#include "plugins/CutterPlugin.h" #include "plugins/CutterPlugin.h"
#include "common/BasicBlockHighlighter.h"
class RCoreLocked class RCoreLocked
{ {
@ -728,6 +729,7 @@ public:
RCoreLocked core() const; RCoreLocked core() const;
static QString ansiEscapeToHtml(const QString &text); static QString ansiEscapeToHtml(const QString &text);
BasicBlockHighlighter *getBBHighlighter();
signals: signals:
void refreshAll(); void refreshAll();
@ -783,6 +785,7 @@ private:
QErrorMessage msgBox; QErrorMessage msgBox;
bool emptyGraph = false; bool emptyGraph = false;
BasicBlockHighlighter *bbHighlighter;
}; };

View File

@ -298,7 +298,8 @@ SOURCES += \
dialogs/LoadNewTypesDialog.cpp \ dialogs/LoadNewTypesDialog.cpp \
widgets/SdbWidget.cpp \ widgets/SdbWidget.cpp \
common/PythonManager.cpp \ common/PythonManager.cpp \
plugins/PluginManager.cpp plugins/PluginManager.cpp \
common/BasicBlockHighlighter.cpp
HEADERS += \ HEADERS += \
Cutter.h \ Cutter.h \
@ -411,7 +412,8 @@ HEADERS += \
dialogs/LoadNewTypesDialog.h \ dialogs/LoadNewTypesDialog.h \
widgets/SdbWidget.h \ widgets/SdbWidget.h \
common/PythonManager.h \ common/PythonManager.h \
plugins/PluginManager.h plugins/PluginManager.h \
common/BasicBlockHighlighter.h
FORMS += \ FORMS += \
dialogs/AboutDialog.ui \ dialogs/AboutDialog.ui \

View File

@ -7,6 +7,7 @@
<object-type name="CutterCore" /> <object-type name="CutterCore" />
<object-type name="Configuration" /> <object-type name="Configuration" />
<object-type name="MainWindow" /> <object-type name="MainWindow" />
<object-type name="BasicBlockHighlighter" />
<object-type name="CutterDockWidget" /> <object-type name="CutterDockWidget" />
<object-type name="CutterPlugin"> <object-type name="CutterPlugin">
<modify-function signature="getName()const"> <modify-function signature="getName()const">

View File

@ -0,0 +1,48 @@
#include "BasicBlockHighlighter.h"
BasicBlockHighlighter::BasicBlockHighlighter()
{
}
BasicBlockHighlighter::~BasicBlockHighlighter()
{
for (BasicBlockIt itr = bbMap.begin(); itr != bbMap.end(); itr++) {
delete itr->second;
}
}
/*!
* \brief Highlight the basic block at address
*/
void BasicBlockHighlighter::highlight(RVA address, const QColor &color)
{
BasicBlock *block = new BasicBlock;
block->address = address;
block->color = color;
bbMap[address] = block;
}
/*!
* \brief Clear the basic block highlighting
*/
void BasicBlockHighlighter::clear(RVA address)
{
bbMap.erase(address);
}
/*!
* \brief Return a highlighted basic block
*
* If there is nothing to highlight at specified address, returns nullptr
*/
BasicBlock *BasicBlockHighlighter::getBasicBlock(RVA address)
{
BasicBlockIt it;
it = bbMap.find(address);
if (it != bbMap.end()) {
return it->second;
}
return nullptr;
}

View File

@ -0,0 +1,30 @@
#ifndef BASICKBLOCKHIGHLIGHTER_H
#define BASICKBLOCKHIGHLIGHTER_H
class BasicBlockHighlighter;
#include "Cutter.h"
#include <map>
struct BasicBlock {
RVA address;
QColor color;
};
typedef std::map<RVA, BasicBlock*>::iterator BasicBlockIt;
class BasicBlockHighlighter
{
public:
BasicBlockHighlighter();
~BasicBlockHighlighter();
void highlight(RVA address, const QColor &color);
void clear(RVA address);
BasicBlock *getBasicBlock(RVA address);
private:
std::map<RVA, BasicBlock*> bbMap;
};
#endif // BASICBLOCKHIGHLIGHTER_H

View File

@ -23,6 +23,7 @@
#include "common/CachedFontMetrics.h" #include "common/CachedFontMetrics.h"
#include "common/TempConfig.h" #include "common/TempConfig.h"
#include "common/SyntaxHighlighter.h" #include "common/SyntaxHighlighter.h"
#include "common/BasicBlockHighlighter.h"
DisassemblerGraphView::DisassemblerGraphView(QWidget *parent) DisassemblerGraphView::DisassemblerGraphView(QWidget *parent)
: GraphView(parent), : GraphView(parent),
@ -429,8 +430,18 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
p.setBrush(disassemblyBackgroundColor); p.setBrush(disassemblyBackgroundColor);
} }
// Draw basic block background
p.drawRect(blockX, blockY, p.drawRect(blockX, blockY,
block.width, block.height); block.width, block.height);
auto bb = Core()->getBBHighlighter()->getBasicBlock(block.entry);
if (bb) {
QColor color(bb->color);
color.setAlphaF(0.5);
p.setBrush(color);
// Add basic block highlighting transparent color
p.drawRect(blockX, blockY,
block.width, block.height);
}
// Draw different background for selected instruction // Draw different background for selected instruction
if (selected_instruction != RVA_INVALID) { if (selected_instruction != RVA_INVALID) {
@ -440,39 +451,16 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
break; break;
} }
auto selected = instr.addr == selected_instruction; auto selected = instr.addr == selected_instruction;
//auto traceCount = dbgfunctions->GetTraceRecordHitCount(instr.addr); if (selected) {
auto traceCount = 0;
if (selected && traceCount) {
p.fillRect(QRect(static_cast<int>(blockX + charWidth), y,
static_cast<int>(block.width - (10 + 2 * charWidth)),
int(instr.text.lines.size()) * charHeight), disassemblyTracedSelectionColor);
} else if (selected) {
p.fillRect(QRect(static_cast<int>(blockX + charWidth), y, p.fillRect(QRect(static_cast<int>(blockX + charWidth), y,
static_cast<int>(block.width - (10 + 2 * charWidth)), static_cast<int>(block.width - (10 + 2 * charWidth)),
int(instr.text.lines.size()) * charHeight), disassemblySelectionColor); int(instr.text.lines.size()) * charHeight), disassemblySelectionColor);
} else if (traceCount) {
// Color depending on how often a sequence of code is executed
int exponent = 1;
while (traceCount >>= 1) //log2(traceCount)
exponent++;
int colorDiff = (exponent * exponent) / 2;
// If the user has a light trace background color, substract
if (disassemblyTracedColor.blue() > 160)
colorDiff *= -1;
p.fillRect(QRect(static_cast<int>(blockX + charWidth), y,
static_cast<int>(block.width - (10 + 2 * charWidth)),
int(instr.text.lines.size()) * charHeight),
QColor(disassemblyTracedColor.red(),
disassemblyTracedColor.green(),
std::max(0, std::min(256, disassemblyTracedColor.blue() + colorDiff))));
} }
y += int(instr.text.lines.size()) * charHeight; y += int(instr.text.lines.size()) * charHeight;
} }
} }
// highlight selected tokens // Highlight selected tokens
if (highlight_token != nullptr) { if (highlight_token != nullptr) {
int y = static_cast<int>(blockY + (2 * charWidth) + (db.header_text.lines.size() * charHeight)); int y = static_cast<int>(blockY + (2 * charWidth) + (db.header_text.lines.size() * charHeight));
int tokenWidth = mFontMetrics->width(highlight_token->content); int tokenWidth = mFontMetrics->width(highlight_token->content);
@ -508,7 +496,7 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
} }
} }
// highlight program counter // Highlight program counter
if (PCInBlock) { if (PCInBlock) {
int y = static_cast<int>(blockY + (2 * charWidth) + (db.header_text.lines.size() * charHeight)); int y = static_cast<int>(blockY + (2 * charWidth) + (db.header_text.lines.size() * charHeight));
for (const Instr &instr : db.instrs) { for (const Instr &instr : db.instrs) {

View File

@ -192,8 +192,6 @@ private:
QColor disassemblySelectedBackgroundColor; QColor disassemblySelectedBackgroundColor;
QColor disassemblySelectionColor; QColor disassemblySelectionColor;
QColor PCSelectionColor; QColor PCSelectionColor;
QColor disassemblyTracedColor;
QColor disassemblyTracedSelectionColor;
QColor jmpColor; QColor jmpColor;
QColor brtrueColor; QColor brtrueColor;
QColor brfalseColor; QColor brfalseColor;

View File

@ -52,6 +52,15 @@ void OverviewView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
p.setBrush(disassemblyBackgroundColor); p.setBrush(disassemblyBackgroundColor);
p.drawRect(blockX, blockY, p.drawRect(blockX, blockY,
block.width, block.height); block.width, block.height);
// Draw basic block highlighting/tracing
auto bb = Core()->getBBHighlighter()->getBasicBlock(block.entry);
if (bb) {
QColor color(bb->color);
color.setAlphaF(0.5);
p.setBrush(color);
p.drawRect(block.x, block.y,
block.width, block.height);
}
} }
void OverviewView::paintEvent(QPaintEvent *event) void OverviewView::paintEvent(QPaintEvent *event)