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
setConfig("scr.interactive", false);
// Initialize graph node highlighter
bbHighlighter = new BasicBlockHighlighter();
// Initialize Async tasks manager
asyncTaskManager = new AsyncTaskManager(this);
}
@ -231,6 +235,7 @@ bool CutterCore::sdbSet(QString path, QString key, QString val)
CutterCore::~CutterCore()
{
delete bbHighlighter;
r_core_free(this->core_);
r_cons_free();
}
@ -2628,3 +2633,8 @@ QString CutterCore::ansiEscapeToHtml(const QString &text)
free(html);
return r;
}
BasicBlockHighlighter* CutterCore::getBBHighlighter()
{
return bbHighlighter;
}

View File

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

View File

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

View File

@ -7,6 +7,7 @@
<object-type name="CutterCore" />
<object-type name="Configuration" />
<object-type name="MainWindow" />
<object-type name="BasicBlockHighlighter" />
<object-type name="CutterDockWidget" />
<object-type name="CutterPlugin">
<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/TempConfig.h"
#include "common/SyntaxHighlighter.h"
#include "common/BasicBlockHighlighter.h"
DisassemblerGraphView::DisassemblerGraphView(QWidget *parent)
: GraphView(parent),
@ -429,8 +430,18 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
p.setBrush(disassemblyBackgroundColor);
}
// Draw basic block background
p.drawRect(blockX, blockY,
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
if (selected_instruction != RVA_INVALID) {
@ -440,39 +451,16 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
break;
}
auto selected = instr.addr == selected_instruction;
//auto traceCount = dbgfunctions->GetTraceRecordHitCount(instr.addr);
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) {
if (selected) {
p.fillRect(QRect(static_cast<int>(blockX + charWidth), y,
static_cast<int>(block.width - (10 + 2 * charWidth)),
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;
}
}
// highlight selected tokens
// Highlight selected tokens
if (highlight_token != nullptr) {
int y = static_cast<int>(blockY + (2 * charWidth) + (db.header_text.lines.size() * charHeight));
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) {
int y = static_cast<int>(blockY + (2 * charWidth) + (db.header_text.lines.size() * charHeight));
for (const Instr &instr : db.instrs) {

View File

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

View File

@ -52,6 +52,15 @@ void OverviewView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
p.setBrush(disassemblyBackgroundColor);
p.drawRect(blockX, blockY,
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)