Graph : Move controlFlowGraph into it's own class to allow for stuff to properly be deleted when reloading the program/loading a different program
Graph : Fixed two bugs causing crashes + some cleanup/refactor
This commit is contained in:
parent
6ee0e5f7d0
commit
656eeff13d
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef _GLOBAL_H
|
||||
#define _GLOBAL_H
|
||||
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#define _WIN32_WINNT 0x0601
|
||||
#define WINVER 0x0501
|
||||
#define _WIN32_IE 0x0500
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ void ControlFlowAnalysis::Analyse()
|
|||
|
||||
dprintf("Analysis finished!\n");
|
||||
|
||||
// TODO : Fix this
|
||||
PARENTMAP *_parentsTemp = new PARENTMAP(_parentMap);
|
||||
BASICBLOCKMAP *_blocksTemp = new BASICBLOCKMAP(_blocks);
|
||||
|
||||
|
|
|
|||
|
|
@ -1414,6 +1414,7 @@ const dsint Disassembly::currentEIP() const
|
|||
void Disassembly::disassembleAt(dsint parVA, dsint parCIP)
|
||||
{
|
||||
emit drawGraphAtAddress(parVA);
|
||||
|
||||
disassembleAt(parVA, parCIP, true, -1);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ GraphNode::GraphNode() : QFrame()
|
|||
}
|
||||
|
||||
GraphNode::GraphNode(std::vector<Instruction_t> &instructionsVector, duint address)
|
||||
:
|
||||
mAddress(address),
|
||||
mInstructionsVector(instructionsVector),
|
||||
mHighlightInstructionAt(-1)
|
||||
{
|
||||
mAddress = address;
|
||||
mInstructionsVector = instructionsVector;
|
||||
mHighlightInstructionAt = -1;
|
||||
|
||||
updateTokensVector();
|
||||
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
|
|
|
|||
|
|
@ -9,58 +9,59 @@ class Node
|
|||
{
|
||||
public:
|
||||
explicit Node(ogdf::Graph* G, ogdf::GraphAttributes* GA, ogdf::node ogdfNode, T data)
|
||||
{
|
||||
this->_G = G;
|
||||
this->_GA = GA;
|
||||
this->_ogdfNode = ogdfNode;
|
||||
this->_data = data;
|
||||
this->_left = nullptr;
|
||||
this->_right = nullptr;
|
||||
}
|
||||
:
|
||||
mG(G),
|
||||
mGA(GA),
|
||||
mData(data),
|
||||
mOgdfNode(ogdfNode),
|
||||
mLeft(nullptr),
|
||||
mRight(nullptr)
|
||||
{}
|
||||
|
||||
Node<T>* setLeft(Node* left)
|
||||
{
|
||||
return left ? this->_left = makeNodeWithEdge(left) : nullptr;
|
||||
return left ? mLeft = makeNodeWithEdge(left) : nullptr;
|
||||
}
|
||||
Node<T>* setRight(Node* right)
|
||||
{
|
||||
return right ? this->_right = makeNodeWithEdge(right) : nullptr;
|
||||
return right ? mRight = makeNodeWithEdge(right) : nullptr;
|
||||
}
|
||||
|
||||
Node<T>* setData(T data)
|
||||
{
|
||||
this->_data = data;
|
||||
mData = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
Node<T>* left()
|
||||
Node<T>* left() const
|
||||
{
|
||||
return this->_left;
|
||||
return mLeft;
|
||||
}
|
||||
Node<T>* right()
|
||||
Node<T>* right() const
|
||||
{
|
||||
return this->_right;
|
||||
return mRight;
|
||||
}
|
||||
T data()
|
||||
T data() const
|
||||
{
|
||||
return this->_data;
|
||||
return mData;
|
||||
}
|
||||
ogdf::node ogdfNode()
|
||||
ogdf::node ogdfNode() const
|
||||
{
|
||||
return this->_ogdfNode;
|
||||
return mOgdfNode;
|
||||
}
|
||||
|
||||
private:
|
||||
Node<T>* _left;
|
||||
Node<T>* _right;
|
||||
T _data;
|
||||
ogdf::Graph* _G;
|
||||
ogdf::GraphAttributes* _GA;
|
||||
ogdf::node _ogdfNode;
|
||||
T mData;
|
||||
Node<T>* mLeft;
|
||||
Node<T>* mRight;
|
||||
ogdf::Graph* mG;
|
||||
ogdf::GraphAttributes* mGA;
|
||||
ogdf::node mOgdfNode;
|
||||
|
||||
Node* makeNodeWithEdge(Node<T>* node)
|
||||
{
|
||||
auto edge = this->_G->newEdge(this->_ogdfNode, node->_ogdfNode);
|
||||
this->_GA->arrowType(edge) = ogdf::EdgeArrow::eaLast;
|
||||
auto edge = mG->newEdge(mOgdfNode, node->mOgdfNode);
|
||||
mGA->arrowType(edge) = ogdf::EdgeArrow::eaLast;
|
||||
return node;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,39 +11,36 @@
|
|||
#include <ogdf/basic/GraphAttributes.h>
|
||||
#include "Imports.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
template <typename T>
|
||||
class Tree
|
||||
{
|
||||
public:
|
||||
explicit Tree(ogdf::Graph* G, ogdf::GraphAttributes* GA)
|
||||
{
|
||||
this->_G = G;
|
||||
this->_GA = GA;
|
||||
}
|
||||
explicit Tree(ogdf::Graph* G, ogdf::GraphAttributes* GA) : mG(G), mGA(GA)
|
||||
{}
|
||||
|
||||
Node<T>* newNode(T data)
|
||||
{
|
||||
ogdf::node ogdfNode = _G->newNode();
|
||||
Node<T> *node = new Node<T>(_G, _GA, ogdfNode, data);
|
||||
_ogdfDataMap[ogdfNode] = node;
|
||||
_nodePool.push_back(unique_ptr<Node<T>>(node));
|
||||
ogdf::node ogdfNode = mG->newNode();
|
||||
auto node = new Node<T>(mG, mGA, ogdfNode, data);
|
||||
mOgdfDataMap[ogdfNode] = node;
|
||||
mNodePool.push_back(std::unique_ptr<Node<T>>(node));
|
||||
return node;
|
||||
}
|
||||
Node<T>* findNode(ogdf::node ogdfNode)
|
||||
{
|
||||
auto found = _ogdfDataMap.find(ogdfNode);
|
||||
return found != _ogdfDataMap.end() ? found->second : nullptr;
|
||||
auto found = mOgdfDataMap.find(ogdfNode);
|
||||
return found != mOgdfDataMap.end() ? found->second : nullptr;
|
||||
}
|
||||
Node<T>* findNodeByAddress(duint address)
|
||||
{
|
||||
auto it = std::find_if(_ogdfDataMap.begin(), _ogdfDataMap.end(), [address](const pair<ogdf::node, Node<T>* > &itr)
|
||||
auto it = std::find_if(mOgdfDataMap.begin(), mOgdfDataMap.end(), [address](const std::pair<ogdf::node, Node<T>* > &itr)
|
||||
{
|
||||
return itr.second->data()->address() == address;
|
||||
return itr.second && itr.second->data() && itr.second->data()->address() == address;
|
||||
});
|
||||
|
||||
// If found
|
||||
if(it != _ogdfDataMap.end())
|
||||
if(it != mOgdfDataMap.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
|
@ -55,23 +52,18 @@ public:
|
|||
|
||||
void clear()
|
||||
{
|
||||
for(duint i=0; i < _nodePool.size(); i++)
|
||||
_nodePool[i].reset();
|
||||
for(duint i=0; i < mNodePool.size(); i++)
|
||||
mNodePool[i].reset();
|
||||
|
||||
_nodePool.clear();
|
||||
|
||||
map<ogdf::node, Node<T>*>::iterator it = _ogdfDataMap.begin();
|
||||
for(it; it != _ogdfDataMap.end(); it++)
|
||||
delete it->second;
|
||||
|
||||
_ogdfDataMap.clear();
|
||||
mNodePool.clear();
|
||||
mOgdfDataMap.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
ogdf::Graph* _G;
|
||||
ogdf::GraphAttributes* _GA;
|
||||
vector<unique_ptr<Node<T>>> _nodePool;
|
||||
map<ogdf::node, Node<T>*> _ogdfDataMap;
|
||||
ogdf::Graph* mG;
|
||||
ogdf::GraphAttributes* mGA;
|
||||
std::vector<std::unique_ptr<Node<T>>> mNodePool;
|
||||
std::map<ogdf::node, Node<T>*> mOgdfDataMap;
|
||||
};
|
||||
|
||||
#endif //_TREE_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,408 @@
|
|||
#include "ControlFlowGraph.h"
|
||||
#include "Configuration.h"
|
||||
|
||||
void deleteGraphNodeVector(GRAPHNODEVECTOR* graphNodeVector)
|
||||
{
|
||||
for(auto& ptr : *graphNodeVector)
|
||||
ptr->deleteLater();
|
||||
}
|
||||
|
||||
ControlFlowGraph::ControlFlowGraph(QWidget *parent) : QWidget(parent),
|
||||
mParentsInfo(nullptr),
|
||||
mBasicBlockInfo(nullptr),
|
||||
mDisas(new QBeaEngine(-1)),
|
||||
mScene(new QGraphicsScene()),
|
||||
mGraphicsView(new QGraphicsView()),
|
||||
bProgramInitialized(false),
|
||||
mVLayout(new QVBoxLayout()),
|
||||
mGraphNodeVector(new GRAPHNODEVECTOR, deleteGraphNodeVector)
|
||||
{
|
||||
|
||||
mScene->setBackgroundBrush(ConfigColor("DisassemblyBackgroundColor"));
|
||||
mGraphicsView->setScene(mScene);
|
||||
|
||||
mVLayout->addWidget(mGraphicsView);
|
||||
setLayout(mVLayout);
|
||||
|
||||
|
||||
connect(Bridge::getBridge(), SIGNAL(setControlFlowInfos(duint*)), this, SLOT(setControlFlowInfosSlot(duint*)));
|
||||
connect(Bridge::getBridge(), SIGNAL(disassembleAt(dsint,dsint)), this, SLOT(disassembleAtSlot(dsint, dsint)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ControlFlowGraph::startControlFlowAnalysis()
|
||||
{
|
||||
DbgCmdExec(QString("cfanalyze").toUtf8().constData());
|
||||
}
|
||||
|
||||
void ControlFlowGraph::setUnconditionalBranchEdgeColor()
|
||||
{
|
||||
for(auto const &nodeGraphEdge : mNodeGraphEdge)
|
||||
{
|
||||
if(nodeGraphEdge.second.size() == 1)
|
||||
nodeGraphEdge.second.at(0)->setEdgeColor(Qt::blue);
|
||||
}
|
||||
}
|
||||
|
||||
ControlFlowGraph::~ControlFlowGraph()
|
||||
{
|
||||
mGraphNodeVector.reset();
|
||||
mGraphicsView->deleteLater();
|
||||
mScene->deleteLater();
|
||||
mVLayout->deleteLater();
|
||||
mTree.reset();
|
||||
mOHL.reset();
|
||||
mSL.reset();
|
||||
mGA.reset();
|
||||
delete mBasicBlockInfo;
|
||||
delete mParentsInfo;
|
||||
delete mDisas;
|
||||
}
|
||||
|
||||
void ControlFlowGraph::setupGraph()
|
||||
{
|
||||
using namespace ogdf;
|
||||
using namespace std;
|
||||
|
||||
|
||||
//initialize graph
|
||||
mGA = make_unique<GraphAttributes>(mG, GraphAttributes::nodeGraphics |
|
||||
GraphAttributes::edgeGraphics |
|
||||
GraphAttributes::nodeLabel |
|
||||
GraphAttributes::nodeStyle |
|
||||
GraphAttributes::edgeType |
|
||||
GraphAttributes::edgeArrow |
|
||||
GraphAttributes::edgeStyle);
|
||||
|
||||
|
||||
//add nodes
|
||||
mTree = make_unique<Tree<GraphNode*>>(&mG, mGA.get());
|
||||
|
||||
setupTree();
|
||||
|
||||
addGraphToScene();
|
||||
|
||||
// Make sure there is some spacing
|
||||
QRectF sceneRect = mGraphicsView->sceneRect();
|
||||
sceneRect.adjust(-20, -20, 20, 20);
|
||||
mGraphicsView->setSceneRect(sceneRect);
|
||||
|
||||
mGraphicsView->show();
|
||||
}
|
||||
|
||||
|
||||
void ControlFlowGraph::setupTree(duint va)
|
||||
{
|
||||
using namespace ogdf;
|
||||
using namespace std;
|
||||
|
||||
QTextStream out(stdout);
|
||||
BASICBLOCKMAP::iterator it;
|
||||
std::vector<Instruction_t> instructionsVector;
|
||||
|
||||
// Clear graph and tree
|
||||
mG.clear();
|
||||
mTree->clear();
|
||||
mGraphNodeVector->clear();
|
||||
|
||||
if(!va)
|
||||
it = mBasicBlockInfo->begin();
|
||||
else
|
||||
it = mBasicBlockInfo->find(va);
|
||||
|
||||
// Couldn't find the basic block of the VA
|
||||
if(it == mBasicBlockInfo->end())
|
||||
return;
|
||||
|
||||
|
||||
// Disassemble the instruction at the address
|
||||
readBasicBlockInstructions(it, instructionsVector);
|
||||
|
||||
// Add root node first
|
||||
duint addr = it->first;
|
||||
mGraphNodeVector->push_back( make_unique<GraphNode>(instructionsVector, addr) );
|
||||
connect(mGraphNodeVector->back().get(), SIGNAL(drawGraphAt(duint)), this, SLOT(drawGraphAtSlot(duint)), Qt::QueuedConnection);
|
||||
|
||||
Node<GraphNode *> *rootNode = mTree->newNode(mGraphNodeVector->back().get());
|
||||
addAllNodes(it, rootNode);
|
||||
}
|
||||
|
||||
void ControlFlowGraph::setupGraphLayout()
|
||||
{
|
||||
using namespace ogdf;
|
||||
using namespace std;
|
||||
|
||||
|
||||
// TODO : Better way to do this
|
||||
if(mOHL.get() && mSL.get())
|
||||
{
|
||||
mSL->call(*mGA);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
mOHL = make_unique<OptimalHierarchyLayout>();
|
||||
mOHL->nodeDistance(25.0);
|
||||
mOHL->layerDistance(50.0);
|
||||
mOHL->fixedLayerDistance(false);
|
||||
mOHL->weightBalancing(0.0);
|
||||
mOHL->weightSegments(0.0);
|
||||
|
||||
mSL = make_unique<SugiyamaLayout>();
|
||||
mSL->setRanking(new OptimalRanking);
|
||||
mSL->setCrossMin(new MedianHeuristic);
|
||||
mSL->alignSiblings(false);
|
||||
mSL->setLayout(mOHL.get());
|
||||
mSL->call(*mGA);
|
||||
}
|
||||
|
||||
void ControlFlowGraph::adjustNodesSize()
|
||||
{
|
||||
// Adjust node size
|
||||
ogdf::node v;
|
||||
forall_nodes(v, mG)
|
||||
{
|
||||
Node<GraphNode* > *node = mTree->findNode(v);
|
||||
if (node)
|
||||
{
|
||||
QRectF rect = node->data()->boundingRect();
|
||||
mGA->width(v) = rect.width();
|
||||
mGA->height(v) = rect.height();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ControlFlowGraph::addGraphToScene()
|
||||
{
|
||||
using namespace ogdf;
|
||||
|
||||
mNodeGraphEdge.clear();
|
||||
mScene->clear();
|
||||
|
||||
adjustNodesSize();
|
||||
|
||||
// Apply the graph layout after we've set the nodes sizes
|
||||
setupGraphLayout();
|
||||
|
||||
addNodesToScene();
|
||||
|
||||
addEdgesToScene();
|
||||
|
||||
// Change unconditionalBranches colors to something different than for conditional branches
|
||||
setUnconditionalBranchEdgeColor();
|
||||
|
||||
mGraphicsView->ensureVisible(mScene->itemsBoundingRect());
|
||||
|
||||
// Make sure there is some spacing
|
||||
mScene->sceneRect().adjust(-20, -20, 20, 20);
|
||||
mGraphicsView->setSceneRect(mScene->sceneRect());
|
||||
}
|
||||
|
||||
void ControlFlowGraph::addNodesToScene()
|
||||
{
|
||||
ogdf::node v;
|
||||
forall_nodes(v, mG)
|
||||
{
|
||||
Node<GraphNode* > *node = mTree->findNode(v);
|
||||
if (node)
|
||||
{
|
||||
//draw node using x,y
|
||||
QRectF rect = node->data()->boundingRect();
|
||||
qreal x = mGA->x(v) - (rect.width()/2);
|
||||
qreal y = mGA->y(v) - (rect.height()/2);
|
||||
node->data()->setGeometry(x, y, rect.width(), rect.height());
|
||||
mScene->addWidget(node->data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ControlFlowGraph::addEdgesToScene()
|
||||
{
|
||||
//draw edges
|
||||
ogdf::edge e;
|
||||
forall_edges(e, mG)
|
||||
{
|
||||
const auto bends = mGA->bends(e);
|
||||
const auto source = e->source();
|
||||
const auto target = e->target();
|
||||
|
||||
GraphNode* sourceGraphNode = mTree->findNode(source)->data();
|
||||
GraphNode* targetGraphNode = mTree->findNode(target)->data();
|
||||
|
||||
QRectF sourceRect = sourceGraphNode->geometry();
|
||||
QRectF targetRect = targetGraphNode->geometry();
|
||||
sourceRect.adjust(-4, -4, 4, 4);
|
||||
targetRect.adjust(-4, -4, 4, 4);
|
||||
|
||||
QPointF start(mGA->x(source), mGA->y(source));
|
||||
QPointF end(mGA->x(target), mGA->y(target));
|
||||
|
||||
GraphEdge* edge = nullptr;
|
||||
auto const sourceNodeLeft = mTree->findNode(source)->left();
|
||||
|
||||
if(sourceNodeLeft && sourceNodeLeft->data()->address() == targetGraphNode->address())
|
||||
edge = new GraphEdge(start, end, bends, sourceRect, targetRect, GraphEdge::EDGE_LEFT);
|
||||
else
|
||||
edge = new GraphEdge(start, end, bends, sourceRect, targetRect, GraphEdge::EDGE_RIGHT);
|
||||
|
||||
mNodeGraphEdge[source].push_back(std::unique_ptr<GraphEdge>(edge));
|
||||
mScene->addItem(edge);
|
||||
}
|
||||
}
|
||||
|
||||
void ControlFlowGraph::addAllNodes(BASICBLOCKMAP::iterator it, Node<GraphNode *> *parentNode)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
QByteArray byteArray(MAX_STRING_SIZE, 0);
|
||||
duint left = it->second.left; // Left child addr
|
||||
duint right = it->second.right; // Right child addr
|
||||
|
||||
// No childs
|
||||
if(!left && !right)
|
||||
return;
|
||||
|
||||
for(int i=0; i < 2; i++)
|
||||
{
|
||||
// If not left or right child continue..
|
||||
if((i == 0 && !left) || (i == 1 && !right))
|
||||
continue;
|
||||
|
||||
BASICBLOCKMAP::iterator itChild;
|
||||
Node<GraphNode*>* node = nullptr;
|
||||
|
||||
// Left
|
||||
if(i == 0)
|
||||
{
|
||||
itChild = mBasicBlockInfo->find(left);
|
||||
node = mTree->findNodeByAddress(left);
|
||||
}
|
||||
//Right
|
||||
else
|
||||
{
|
||||
itChild = mBasicBlockInfo->find(right);
|
||||
node = mTree->findNodeByAddress(right);
|
||||
}
|
||||
|
||||
// If we found the basicblock for left or right
|
||||
if(itChild != mBasicBlockInfo->end())
|
||||
{
|
||||
duint childNodeAddr;
|
||||
|
||||
if(i == 0) // Add node to left of parentNode
|
||||
childNodeAddr = left;
|
||||
else // Add node to right of parentNode
|
||||
childNodeAddr = right;
|
||||
|
||||
// Node does not exist, create it
|
||||
if(node == nullptr)
|
||||
{
|
||||
std::vector<Instruction_t> instructionsVector;
|
||||
readBasicBlockInstructions(itChild, instructionsVector);
|
||||
|
||||
mGraphNodeVector->push_back( make_unique<GraphNode>(instructionsVector, childNodeAddr) );
|
||||
|
||||
node = mTree->newNode(mGraphNodeVector->back().get());
|
||||
|
||||
connect(mGraphNodeVector->back().get(), SIGNAL(drawGraphAt(duint)), this, SLOT(drawGraphAtSlot(duint)), Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
Node<GraphNode*>* newParentNode = nullptr;
|
||||
Node <GraphNode*>* parentNodeLeftRight = nullptr;
|
||||
|
||||
if(i == 0)
|
||||
parentNodeLeftRight = parentNode->left();
|
||||
else
|
||||
parentNodeLeftRight = parentNode->right();
|
||||
|
||||
// Edge already exists between parentNode and left / right, we've been here before..
|
||||
if(parentNodeLeftRight && (parentNodeLeftRight->data()->address() == left || parentNodeLeftRight->data()->address() == right))
|
||||
return;
|
||||
|
||||
if(i == 0)
|
||||
newParentNode = parentNode->setLeft(node);
|
||||
else
|
||||
newParentNode = parentNode->setRight(node);
|
||||
|
||||
addAllNodes(itChild, newParentNode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ControlFlowGraph::setControlFlowInfosSlot(duint *controlFlowInfos)
|
||||
{
|
||||
if(controlFlowInfos)
|
||||
{
|
||||
mParentsInfo = (PARENTMAP*)(((CONTROLFLOWINFOS*)controlFlowInfos)->parents);
|
||||
mBasicBlockInfo = (BASICBLOCKMAP*)(((CONTROLFLOWINFOS*)controlFlowInfos)->blocks);
|
||||
setupGraph();
|
||||
}
|
||||
}
|
||||
|
||||
bool ControlFlowGraph::findBasicBlock(duint& va)
|
||||
{
|
||||
if(mBasicBlockInfo == nullptr)
|
||||
return false;
|
||||
|
||||
if(!mBasicBlockInfo->size())
|
||||
return false;
|
||||
|
||||
bool bFound = false;
|
||||
BASICBLOCKMAP::iterator it = mBasicBlockInfo->find(va);
|
||||
|
||||
// If the block was not found by addr, check if it belongs to a basic block
|
||||
if(it == mBasicBlockInfo->end())
|
||||
{
|
||||
for(it = mBasicBlockInfo->begin(); it != mBasicBlockInfo->end(); it++)
|
||||
{
|
||||
if(va >= it->second.start && va <= it->second.end)
|
||||
{
|
||||
va = it->first;
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
bFound = true;
|
||||
|
||||
return bFound;
|
||||
}
|
||||
|
||||
void ControlFlowGraph::readBasicBlockInstructions(BASICBLOCKMAP::iterator it, std::vector<Instruction_t> &instructionsVector)
|
||||
{
|
||||
duint addr = it->first;
|
||||
duint startAddr = it->second.start;
|
||||
duint endAddr = it->second.end;
|
||||
duint baseAddr = DbgMemFindBaseAddr(addr, 0);
|
||||
QByteArray byteArray(MAX_STRING_SIZE, 0);
|
||||
|
||||
// Read basic block instructions
|
||||
for(startAddr; startAddr <= endAddr;)
|
||||
{
|
||||
if(!DbgMemRead(startAddr, reinterpret_cast<unsigned char*>(byteArray.data()), 16))
|
||||
return;
|
||||
|
||||
// Add instruction to the vector
|
||||
Instruction_t wInstruction = mDisas->DisassembleAt(reinterpret_cast<byte_t*>(byteArray.data()), byteArray.length(), 0, baseAddr, startAddr-baseAddr);
|
||||
|
||||
instructionsVector.push_back(wInstruction);
|
||||
startAddr += wInstruction.length;
|
||||
}
|
||||
}
|
||||
|
||||
void ControlFlowGraph::drawGraphAtSlot(duint va)
|
||||
{
|
||||
bool bFound = findBasicBlock(va);
|
||||
|
||||
if(!bFound)
|
||||
return;
|
||||
|
||||
setupTree(va);
|
||||
addGraphToScene();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
#ifndef CONTROLFLOWGRAPH_H
|
||||
#define CONTROLFLOWGRAPH_H
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <QWidget>
|
||||
#include <QWheelEvent>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsView>
|
||||
#include "Bridge.h"
|
||||
#include "Tree.h"
|
||||
#include "GraphNode.h"
|
||||
#include "GraphEdge.h"
|
||||
#include "QBeaEngine.h"
|
||||
#include "capstone_gui.h"
|
||||
#include <ogdf/fileformats/GraphIO.h>
|
||||
#include <ogdf/layered/SugiyamaLayout.h>
|
||||
#include <ogdf/layered/OptimalRanking.h>
|
||||
#include <ogdf/layered/MedianHeuristic.h>
|
||||
#include <ogdf/layered/OptimalHierarchyLayout.h>
|
||||
|
||||
struct BasicBlock
|
||||
{
|
||||
duint start;
|
||||
duint end;
|
||||
duint left;
|
||||
duint right;
|
||||
duint function;
|
||||
|
||||
BasicBlock()
|
||||
{
|
||||
this->start = 0;
|
||||
this->end = 0;
|
||||
this->left = 0;
|
||||
this->right = 0;
|
||||
this->function = 0;
|
||||
}
|
||||
|
||||
BasicBlock(duint start, duint end, duint left, duint right)
|
||||
{
|
||||
this->start = start;
|
||||
this->end = end;
|
||||
this->left = std::min(left, right);
|
||||
this->right = std::max(left, right);
|
||||
this->function = 0;
|
||||
}
|
||||
|
||||
std::string toString()
|
||||
{
|
||||
char buffer[MAX_STRING_SIZE];
|
||||
sprintf_s(buffer, "start:%p,end:%p,left:%p,right:%p,func:%p", start, end, left, right, function);
|
||||
return std::string(buffer);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<duint, BasicBlock> BASICBLOCKMAP;
|
||||
typedef std::map<duint, std::set<duint> > PARENTMAP;
|
||||
typedef std::map<duint, Node<GraphNode *> * > NODEMAP;
|
||||
typedef std::vector<std::unique_ptr<GraphNode>> GRAPHNODEVECTOR;
|
||||
typedef std::map<ogdf::node, std::vector<std::unique_ptr<GraphEdge>> > GRAPHEDGEMAP;
|
||||
|
||||
class ControlFlowGraph : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ControlFlowGraph(QWidget *parent = 0);
|
||||
void startControlFlowAnalysis();
|
||||
void setUnconditionalBranchEdgeColor();
|
||||
~ControlFlowGraph();
|
||||
|
||||
private:
|
||||
void setupGraph();
|
||||
void setupGraphLayout();
|
||||
void setupTree(duint va = 0);
|
||||
void adjustNodesSize();
|
||||
void addGraphToScene();
|
||||
void addNodesToScene();
|
||||
void addEdgesToScene();
|
||||
|
||||
|
||||
void addAllNodes(BASICBLOCKMAP::iterator it, Node<GraphNode *> *parentNode);
|
||||
bool findBasicBlock(duint& va);
|
||||
void readBasicBlockInstructions(BASICBLOCKMAP::iterator it, std::vector<Instruction_t>& instructionsVector);
|
||||
|
||||
public slots:
|
||||
void drawGraphAtSlot(duint va);
|
||||
void setControlFlowInfosSlot(duint *controlFlowInfos);
|
||||
|
||||
private:
|
||||
bool bProgramInitialized;
|
||||
QBeaEngine *mDisas;
|
||||
PARENTMAP *mParentsInfo;
|
||||
BASICBLOCKMAP *mBasicBlockInfo;
|
||||
std::unique_ptr<GRAPHNODEVECTOR, std::function<void(GRAPHNODEVECTOR*)>> mGraphNodeVector;
|
||||
GRAPHEDGEMAP mNodeGraphEdge;
|
||||
ogdf::Graph mG;
|
||||
std::unique_ptr<ogdf::GraphAttributes> mGA;
|
||||
std::unique_ptr<ogdf::SugiyamaLayout> mSL;
|
||||
std::unique_ptr<ogdf::OptimalHierarchyLayout> mOHL;
|
||||
std::unique_ptr<Tree<GraphNode*>> mTree;
|
||||
QVBoxLayout *mVLayout;
|
||||
QGraphicsScene *mScene;
|
||||
QGraphicsView *mGraphicsView;
|
||||
|
||||
};
|
||||
|
||||
#endif // CONTROLFLOWGRAPH_H
|
||||
|
|
@ -1,429 +1,56 @@
|
|||
|
||||
#include "GraphView.h"
|
||||
#include "ui_GraphView.h"
|
||||
#include "Configuration.h"
|
||||
#include <QDebug>
|
||||
|
||||
void deleteControlFlowGraph(ControlFlowGraph* ctrlFlowGraph)
|
||||
{
|
||||
ctrlFlowGraph->deleteLater();
|
||||
}
|
||||
|
||||
|
||||
GraphView::GraphView(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::GraphView)
|
||||
bProgramInitialized(false),
|
||||
mVLayout(new QVBoxLayout()),
|
||||
mControlFlowGraph(new ControlFlowGraph, deleteControlFlowGraph)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
mG = nullptr;
|
||||
mGA = nullptr;
|
||||
mSL = nullptr;
|
||||
mOHL = nullptr;
|
||||
mTree = nullptr;
|
||||
mDisas = new QBeaEngine(-1);
|
||||
mScene = new QGraphicsScene(this);
|
||||
mParentsInfo = nullptr;
|
||||
mBasicBlockInfo = nullptr;
|
||||
mGraphNodeVector = new GRAPHNODEVECTOR;
|
||||
// mNodeGraphEdge = new GRAPHEDGEMAP;
|
||||
bProgramInitialized = false;
|
||||
mVLayout->addWidget(mControlFlowGraph.get());
|
||||
setLayout(mVLayout);
|
||||
|
||||
mScene->setBackgroundBrush(ConfigColor("DisassemblyBackgroundColor"));
|
||||
// ui->graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
// ui->graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
ui->graphicsView->setScene(mScene);
|
||||
|
||||
connect(mScene, SIGNAL(changed(QList<QRectF>)), this, SLOT(sceneChangedSlot(QList<QRectF>)));
|
||||
connect(Bridge::getBridge(), SIGNAL(setControlFlowInfos(duint*)), this, SLOT(setControlFlowInfosSlot(duint*)));
|
||||
connect(Bridge::getBridge(), SIGNAL(disassembleAt(dsint,dsint)), this, SLOT(disassembleAtSlot(dsint, dsint)));
|
||||
connect(Bridge::getBridge(), SIGNAL(dbgStateChanged(DBGSTATE)), this, SLOT(dbgStateChangedSlot(DBGSTATE)));
|
||||
}
|
||||
|
||||
void GraphView::startControlFlowAnalysis()
|
||||
{
|
||||
DbgCmdExec(QString("cfanalyze").toUtf8().constData());
|
||||
}
|
||||
|
||||
void GraphView::showEvent(QShowEvent *event)
|
||||
{
|
||||
// ui->graphicsView->fitInView(mScene->itemsBoundingRect(), Qt::KeepAspectRatio);
|
||||
}
|
||||
|
||||
void GraphView::setUnconditionalBranchEdgeColor()
|
||||
{
|
||||
for(auto const &nodeGraphEdge : mNodeGraphEdge)
|
||||
{
|
||||
if(nodeGraphEdge.second.size() == 1)
|
||||
nodeGraphEdge.second.at(0)->setEdgeColor(Qt::blue);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphView::setupGraph()
|
||||
{
|
||||
using namespace ogdf;
|
||||
|
||||
//initialize graph
|
||||
mG = new Graph;
|
||||
mGA = new GraphAttributes(*mG, GraphAttributes::nodeGraphics |
|
||||
GraphAttributes::edgeGraphics |
|
||||
GraphAttributes::nodeLabel |
|
||||
GraphAttributes::nodeStyle |
|
||||
GraphAttributes::edgeType |
|
||||
GraphAttributes::edgeArrow |
|
||||
GraphAttributes::edgeStyle);
|
||||
|
||||
|
||||
//add nodes
|
||||
mTree = new Tree<GraphNode*>(mG, mGA);
|
||||
|
||||
setupTree();
|
||||
|
||||
addGraphToScene();
|
||||
|
||||
//make sure there is some spacing
|
||||
QRectF sceneRect = ui->graphicsView->sceneRect();
|
||||
sceneRect.adjust(-20, -20, 20, 20);
|
||||
ui->graphicsView->setSceneRect(sceneRect);
|
||||
|
||||
ui->graphicsView->show();
|
||||
}
|
||||
|
||||
|
||||
void GraphView::setupTree(duint va)
|
||||
{
|
||||
using namespace ogdf;
|
||||
|
||||
QTextStream out(stdout);
|
||||
BASICBLOCKMAP::iterator it;
|
||||
QByteArray byteArray(MAX_STRING_SIZE, 0);
|
||||
std::vector<Instruction_t> instructionsVector;
|
||||
|
||||
// Clear graph and tree
|
||||
mG->clear();
|
||||
mTree->clear();
|
||||
|
||||
if(!va)
|
||||
it = mBasicBlockInfo->begin();
|
||||
else
|
||||
it = mBasicBlockInfo->find(va);
|
||||
|
||||
// Couldn't find the basic block of the VA
|
||||
if(it == mBasicBlockInfo->end())
|
||||
return;
|
||||
|
||||
// Disassemble the instruction at the address
|
||||
duint addr = it->first;
|
||||
duint startAddr = it->second.start;
|
||||
duint endAddr = it->second.end;
|
||||
duint baseAddr = DbgMemFindBaseAddr(addr, 0);
|
||||
|
||||
// Read basic block instructions
|
||||
for(startAddr; startAddr <= endAddr;)
|
||||
{
|
||||
if(!DbgMemRead(startAddr, (unsigned char*)byteArray.data(), 16))
|
||||
return;
|
||||
|
||||
Instruction_t wInstruction = mDisas->DisassembleAt((byte_t*)byteArray.data(), byteArray.length(), 0, baseAddr, startAddr-baseAddr);
|
||||
|
||||
// Add instruction to the vector
|
||||
instructionsVector.push_back(wInstruction);
|
||||
startAddr += wInstruction.length;
|
||||
}
|
||||
|
||||
// Add root node first
|
||||
mGraphNodeVector->push_back(new GraphNode(instructionsVector, addr));
|
||||
connect(mGraphNodeVector->back(), SIGNAL(drawGraphAt(duint)), this, SLOT(drawGraphAtSlot(duint)), Qt::QueuedConnection);
|
||||
|
||||
Node<GraphNode *> *rootNode = mTree->newNode(mGraphNodeVector->back());
|
||||
addAllNodes(it, rootNode);
|
||||
}
|
||||
|
||||
void GraphView::setupGraphLayout()
|
||||
{
|
||||
using namespace ogdf;
|
||||
|
||||
// TODO : Better way to do this
|
||||
if(mOHL && mSL)
|
||||
{
|
||||
mSL->call(*mGA);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
mOHL = new OptimalHierarchyLayout;
|
||||
mOHL->nodeDistance(25.0);
|
||||
mOHL->layerDistance(50.0);
|
||||
mOHL->fixedLayerDistance(false);
|
||||
mOHL->weightBalancing(0.0);
|
||||
mOHL->weightSegments(0.0);
|
||||
|
||||
mSL = new SugiyamaLayout;
|
||||
mSL->setRanking(new OptimalRanking);
|
||||
mSL->setCrossMin(new MedianHeuristic);
|
||||
mSL->alignSiblings(false);
|
||||
mSL->setLayout(mOHL);
|
||||
mSL->call(*mGA);
|
||||
}
|
||||
|
||||
void GraphView::addGraphToScene()
|
||||
{
|
||||
using namespace ogdf;
|
||||
|
||||
mNodeGraphEdge.clear();
|
||||
mScene->clear();
|
||||
|
||||
// adjust node size
|
||||
node v;
|
||||
forall_nodes(v, *mG)
|
||||
{
|
||||
Node<GraphNode* > *node = mTree->findNode(v);
|
||||
if (node)
|
||||
{
|
||||
QRectF rect = node->data()->boundingRect();
|
||||
mGA->width(v) = rect.width();
|
||||
mGA->height(v) = rect.height();
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the graph layout after we've set the nodes sizes
|
||||
setupGraphLayout();
|
||||
|
||||
//draw widget contents (nodes)
|
||||
forall_nodes(v, *mG)
|
||||
{
|
||||
Node<GraphNode* > *node = mTree->findNode(v);
|
||||
if (node)
|
||||
{
|
||||
//draw node using x,y
|
||||
QRectF rect = node->data()->boundingRect();
|
||||
qreal x = mGA->x(v) - (rect.width()/2);
|
||||
qreal y = mGA->y(v) - (rect.height()/2);
|
||||
node->data()->setGeometry(x, y, rect.width(), rect.height());
|
||||
mScene->addWidget(node->data());
|
||||
}
|
||||
}
|
||||
|
||||
//draw edges
|
||||
edge e;
|
||||
forall_edges(e, *mG)
|
||||
{
|
||||
const auto bends = mGA->bends(e);
|
||||
const auto source = e->source();
|
||||
const auto target = e->target();
|
||||
|
||||
GraphNode* sourceGraphNode = mTree->findNode(source)->data();
|
||||
GraphNode* targetGraphNode = mTree->findNode(target)->data();
|
||||
|
||||
QRectF sourceRect = sourceGraphNode->geometry();
|
||||
sourceRect.adjust(-4, -4, 4, 4);
|
||||
QRectF targetRect = targetGraphNode->geometry();
|
||||
targetRect.adjust(-4, -4, 4, 4);
|
||||
|
||||
QPointF start(mGA->x(source), mGA->y(source));
|
||||
QPointF end(mGA->x(target), mGA->y(target));
|
||||
|
||||
GraphEdge* edge = nullptr;
|
||||
if(mTree->findNode(source)->left() && mTree->findNode(source)->left()->data()->address() == targetGraphNode->address())
|
||||
edge = new GraphEdge(start, end, bends, sourceRect, targetRect, GraphEdge::EDGE_LEFT);
|
||||
else
|
||||
edge = new GraphEdge(start, end, bends, sourceRect, targetRect, GraphEdge::EDGE_RIGHT);
|
||||
|
||||
mNodeGraphEdge[source].push_back(edge);
|
||||
mScene->addItem(edge);
|
||||
}
|
||||
|
||||
// Change unconditionalBranches colors to something different than for conditional branches
|
||||
setUnconditionalBranchEdgeColor();
|
||||
|
||||
ui->graphicsView->ensureVisible(mScene->itemsBoundingRect());
|
||||
ui->graphicsView->setSceneRect(mScene->sceneRect());
|
||||
}
|
||||
|
||||
void GraphView::addAllNodes(BASICBLOCKMAP::iterator it, Node<GraphNode *> *parentNode)
|
||||
{
|
||||
QTextStream out(stdout);
|
||||
QByteArray byteArray(MAX_STRING_SIZE, 0);
|
||||
duint addr = it->first; // Parent Basic Block addr
|
||||
duint left = it->second.left; // Left child addr
|
||||
duint right = it->second.right; // Right child addr
|
||||
|
||||
// No childs
|
||||
if(!left && !right)
|
||||
return;
|
||||
|
||||
for(int i=0; i < 2; i++)
|
||||
{
|
||||
if((i == 0 && !left) || (i == 1 && !right))
|
||||
continue;
|
||||
|
||||
BASICBLOCKMAP::iterator itChild;
|
||||
Node<GraphNode *> *node = nullptr;
|
||||
|
||||
// Left
|
||||
if(i == 0)
|
||||
{
|
||||
itChild = mBasicBlockInfo->find(left);
|
||||
node = mTree->findNodeByAddress(left);
|
||||
}
|
||||
//Right
|
||||
else
|
||||
{
|
||||
itChild = mBasicBlockInfo->find(right);
|
||||
node = mTree->findNodeByAddress(right);
|
||||
}
|
||||
|
||||
// If we found the basicblock for left or right
|
||||
if(itChild != mBasicBlockInfo->end())
|
||||
{
|
||||
std::vector<Instruction_t> instructionsVector;
|
||||
|
||||
// If the Node doesn't exist yet;
|
||||
if(node == nullptr)
|
||||
{
|
||||
duint startAddr = itChild->second.start;
|
||||
duint endAddr = itChild->second.end;
|
||||
|
||||
// BaseAddr..
|
||||
duint baseAddr = DbgMemFindBaseAddr(addr, 0);
|
||||
|
||||
// Disassemble the BasicBlock instructions
|
||||
for(startAddr; startAddr <= endAddr;)
|
||||
{
|
||||
DbgMemRead(startAddr, (unsigned char*)byteArray.data(), 16);
|
||||
Instruction_t wInstruction = mDisas->DisassembleAt((byte_t*)byteArray.data(), MAX_STRING_SIZE,0, baseAddr, startAddr-baseAddr);
|
||||
|
||||
instructionsVector.push_back(wInstruction);
|
||||
startAddr += wInstruction.length;
|
||||
}
|
||||
}
|
||||
|
||||
// Add node to left of parentNode
|
||||
if(i == 0)
|
||||
{
|
||||
// Node does not exist, create it
|
||||
if(node == nullptr)
|
||||
{
|
||||
mGraphNodeVector->push_back(new GraphNode(instructionsVector, left));
|
||||
node = mTree->newNode(mGraphNodeVector->back());
|
||||
connect(mGraphNodeVector->back(), SIGNAL(drawGraphAt(duint)), this, SLOT(drawGraphAtSlot(duint)), Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
Node<GraphNode *> *newParentNode = nullptr;
|
||||
|
||||
// Edge already exists between parentNode and left / right, we've been here before..
|
||||
if(parentNode->left() && (parentNode->left()->data()->address() == left || parentNode->left()->data()->address() == right))
|
||||
return;
|
||||
else
|
||||
newParentNode = parentNode->setLeft(node);
|
||||
|
||||
addAllNodes(itChild, newParentNode);
|
||||
}
|
||||
|
||||
// Add node to right of parentNode
|
||||
else if(i == 1)
|
||||
{
|
||||
// Node does not exist, create it
|
||||
if(node == nullptr)
|
||||
{
|
||||
mGraphNodeVector->push_back(new GraphNode(instructionsVector, right));
|
||||
node = mTree->newNode(mGraphNodeVector->back());
|
||||
connect((GraphNode*)(mGraphNodeVector->back()), SIGNAL(drawGraphAt(duint)), this, SLOT(drawGraphAtSlot(duint)), Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
Node<GraphNode *> *newParentNode = nullptr;
|
||||
|
||||
// Edge already exists between parentNode and left / right
|
||||
if(parentNode->right() && (parentNode->right()->data()->address() == right || parentNode->right()->data()->address() == left))
|
||||
return;
|
||||
else
|
||||
newParentNode = parentNode->setRight(node);
|
||||
|
||||
addAllNodes(itChild, newParentNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
GraphView::~GraphView()
|
||||
{
|
||||
mScene->clear();
|
||||
|
||||
if(mOHL)
|
||||
delete mOHL;
|
||||
if(mSL)
|
||||
delete mSL;
|
||||
if(mTree)
|
||||
mTree->clear();
|
||||
if(mG)
|
||||
delete mG;
|
||||
if(mGA)
|
||||
delete mGA;
|
||||
|
||||
delete ui;
|
||||
mVLayout->deleteLater();
|
||||
}
|
||||
|
||||
void GraphView::setControlFlowInfosSlot(duint *controlFlowInfos)
|
||||
void GraphView::drawGraphAtSlot(duint va)
|
||||
{
|
||||
if(controlFlowInfos)
|
||||
|
||||
// TODO : Fix this, start analysis from debugger rather than from GUI
|
||||
if(!bProgramInitialized)
|
||||
{
|
||||
mParentsInfo = (PARENTMAP*)(((CONTROLFLOWINFOS*)controlFlowInfos)->parents);
|
||||
mBasicBlockInfo = (BASICBLOCKMAP*)(((CONTROLFLOWINFOS*)controlFlowInfos)->blocks);
|
||||
setupGraph();
|
||||
mControlFlowGraph->startControlFlowAnalysis();
|
||||
bProgramInitialized = true;
|
||||
}
|
||||
|
||||
mControlFlowGraph->drawGraphAtSlot(va);
|
||||
}
|
||||
|
||||
void GraphView::dbgStateChangedSlot(DBGSTATE state)
|
||||
{
|
||||
if(state == initialized)
|
||||
{
|
||||
if(mControlFlowGraph.get() == nullptr)
|
||||
mControlFlowGraph = std::make_unique<ControlFlowGraph>();
|
||||
|
||||
mVLayout->addWidget(mControlFlowGraph.get());
|
||||
}
|
||||
else if(state == stopped)
|
||||
{
|
||||
mVLayout->removeWidget(mControlFlowGraph.get());
|
||||
mControlFlowGraph.reset();
|
||||
bProgramInitialized = false;
|
||||
}
|
||||
|
||||
bool GraphView::findBasicBlock(duint &va)
|
||||
{
|
||||
if(!mBasicBlockInfo)
|
||||
return false;
|
||||
|
||||
if(!mBasicBlockInfo->size())
|
||||
return false;
|
||||
|
||||
bool bFound = false;
|
||||
BASICBLOCKMAP::iterator it = mBasicBlockInfo->find(va);
|
||||
|
||||
// If the block was not found by addr, check if it belongs to a basic block
|
||||
if(it == mBasicBlockInfo->end())
|
||||
{
|
||||
for(it = mBasicBlockInfo->begin(); it != mBasicBlockInfo->end(); it++)
|
||||
{
|
||||
if(va >= it->second.start && va <= it->second.end)
|
||||
{
|
||||
va = it->first;
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
bFound = true;
|
||||
|
||||
return bFound;
|
||||
}
|
||||
|
||||
void GraphView::drawGraphAtSlot(duint va)
|
||||
{
|
||||
bool bFound = findBasicBlock(va);
|
||||
|
||||
if(!bFound)
|
||||
return;
|
||||
|
||||
setupTree(va);
|
||||
addGraphToScene();
|
||||
}
|
||||
|
||||
void GraphView::disassembleAtSlot(dsint parVA, dsint CIP)
|
||||
{
|
||||
Q_UNUSED(CIP)
|
||||
Q_UNUSED(parVA)
|
||||
|
||||
if(!bProgramInitialized)
|
||||
{
|
||||
startControlFlowAnalysis();
|
||||
bProgramInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,68 +1,9 @@
|
|||
#ifndef GRAPHVIEW_H
|
||||
#define GRAPHVIEW_H
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <QWidget>
|
||||
#include <QWheelEvent>
|
||||
#include <QGraphicsScene>
|
||||
#include "QBeaEngine.h"
|
||||
#include "Bridge.h"
|
||||
#include "Tree.h"
|
||||
#include "GraphNode.h"
|
||||
#include "capstone_gui.h"
|
||||
#include <ogdf/fileformats/GraphIO.h>
|
||||
#include <ogdf/layered/SugiyamaLayout.h>
|
||||
#include <ogdf/layered/OptimalRanking.h>
|
||||
#include <ogdf/layered/MedianHeuristic.h>
|
||||
#include <ogdf/layered/OptimalHierarchyLayout.h>
|
||||
#include "GraphEdge.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class GraphView;
|
||||
}
|
||||
|
||||
|
||||
struct BasicBlock
|
||||
{
|
||||
duint start;
|
||||
duint end;
|
||||
duint left;
|
||||
duint right;
|
||||
duint function;
|
||||
|
||||
BasicBlock()
|
||||
{
|
||||
this->start = 0;
|
||||
this->end = 0;
|
||||
this->left = 0;
|
||||
this->right = 0;
|
||||
this->function = 0;
|
||||
}
|
||||
|
||||
BasicBlock(duint start, duint end, duint left, duint right)
|
||||
{
|
||||
this->start = start;
|
||||
this->end = end;
|
||||
this->left = std::min(left, right);
|
||||
this->right = std::max(left, right);
|
||||
this->function = 0;
|
||||
}
|
||||
|
||||
std::string toString()
|
||||
{
|
||||
char buffer[MAX_STRING_SIZE];
|
||||
sprintf_s(buffer, "start:%p,end:%p,left:%p,right:%p,func:%p", start, end, left, right, function);
|
||||
return std::string(buffer);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<duint, BasicBlock> BASICBLOCKMAP; //start of block -> block
|
||||
typedef std::map<duint, std::set<duint> > PARENTMAP; //start child -> parents
|
||||
typedef std::vector<GraphNode* > GRAPHNODEVECTOR;
|
||||
typedef std::map<duint, Node<GraphNode *> * > NODEMAP;
|
||||
typedef std::map<ogdf::node, std::vector<GraphEdge *> > GRAPHEDGEMAP;
|
||||
#include <QVBoxLayout>
|
||||
#include "ControlFlowGraph.h"
|
||||
|
||||
class GraphView : public QWidget
|
||||
{
|
||||
|
|
@ -70,37 +11,16 @@ class GraphView : public QWidget
|
|||
|
||||
public:
|
||||
explicit GraphView(QWidget *parent = 0);
|
||||
void startControlFlowAnalysis();
|
||||
void showEvent(QShowEvent *event);
|
||||
void setUnconditionalBranchEdgeColor();
|
||||
~GraphView();
|
||||
|
||||
public slots:
|
||||
void drawGraphAtSlot(duint va);
|
||||
void disassembleAtSlot(dsint parVA, dsint CIP);
|
||||
void setControlFlowInfosSlot(duint *controlFlowInfos);
|
||||
void dbgStateChangedSlot(DBGSTATE state);
|
||||
void drawGraphAtSlot(duint va);
|
||||
|
||||
private:
|
||||
void setupGraph();
|
||||
void setupGraphLayout();
|
||||
void setupTree(duint va = 0);
|
||||
void addGraphToScene();
|
||||
void addAllNodes(BASICBLOCKMAP::iterator it, Node<GraphNode *> *parentNode);
|
||||
bool findBasicBlock(duint &va);
|
||||
QBeaEngine *mDisas;
|
||||
PARENTMAP *mParentsInfo;
|
||||
BASICBLOCKMAP *mBasicBlockInfo;
|
||||
GRAPHNODEVECTOR *mGraphNodeVector;
|
||||
GRAPHEDGEMAP mNodeGraphEdge;
|
||||
ogdf::Graph *mG;
|
||||
ogdf::GraphAttributes *mGA;
|
||||
ogdf::SugiyamaLayout *mSL;
|
||||
ogdf::OptimalHierarchyLayout *mOHL;
|
||||
QGraphicsScene *mScene;
|
||||
Tree<GraphNode*> *mTree;
|
||||
Ui::GraphView *ui;
|
||||
QVBoxLayout *mVLayout;
|
||||
bool bProgramInitialized;
|
||||
std::unique_ptr<ControlFlowGraph, std::function<void(ControlFlowGraph *ctrlFlowGraph)>> mControlFlowGraph;
|
||||
};
|
||||
|
||||
#endif // GRAPHVIEW_H
|
||||
|
|
|
|||
|
|
@ -151,7 +151,8 @@ SOURCES += \
|
|||
Src/Graph/QGraphScene.cpp \
|
||||
Src/Graph/QGraphView.cpp \
|
||||
Src/Graph/GraphEdge.cpp \
|
||||
Src/Graph/GraphNode.cpp
|
||||
Src/Graph/GraphNode.cpp \
|
||||
Src/Gui/ControlFlowGraph.cpp
|
||||
|
||||
|
||||
HEADERS += \
|
||||
|
|
@ -242,7 +243,8 @@ HEADERS += \
|
|||
Src/Graph/Tree.h \
|
||||
Src/Gui/GraphView.h \
|
||||
Src/Graph/QGraphScene.h \
|
||||
Src/Graph/QGraphView.h
|
||||
Src/Graph/QGraphView.h \
|
||||
Src/Gui/ControlFlowGraph.h
|
||||
|
||||
FORMS += \
|
||||
Src/Gui/MainWindow.ui \
|
||||
|
|
@ -281,11 +283,11 @@ LIBS += -luser32
|
|||
LIBS += -L"$$PWD/../dbg/capstone/" -lcapstone_x86
|
||||
LIBS += -L"$$PWD/Src/ThirdPartyLibs/snowman/" -lsnowman_x86
|
||||
LIBS += -L"$${X64_BIN_DIR}/" -lx32bridge -lcapstone_wrapper
|
||||
LIBS += -L"$${OGDF_BIN_DIR}/" -logdf
|
||||
LIBS += -L"$${OGDF_BIN_DIR}/" -logdf -lcoin
|
||||
} else {
|
||||
# Windows x64 (64bit) specific build
|
||||
LIBS += -L"$$PWD/../dbg/capstone/" -lcapstone_x64
|
||||
LIBS += -L"$$PWD/Src/ThirdPartyLibs/snowman/" -lsnowman_x64
|
||||
LIBS += -L"$${X64_BIN_DIR}/" -lx64bridge -lcapstone_wrapper
|
||||
LIBS += -L"$${OGDF_BIN_DIR}/" -logdf
|
||||
LIBS += -L"$${OGDF_BIN_DIR}/" -logdf -lcoin
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue