#ifndef _GRAPH_H
#define _GRAPH_H
typedef struct
{
duint addr; unsigned char data[15]; } BridgeCFInstruction;
typedef struct
{
duint parentGraph; duint start; duint end; duint brtrue; duint brfalse; duint icount; bool terminal; bool split; bool indirectcall; void* userdata; ListInfo exits; ListInfo instrs; } BridgeCFNodeList;
typedef struct
{
duint entryPoint; void* userdata; ListInfo nodes; } BridgeCFGraphList;
#ifdef __cplusplus
#if _MSC_VER >= 1700 && !defined(NO_CPP11)
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <utility>
struct BridgeCFNode
{
duint parentGraph = 0; duint start = 0; duint end = 0; duint brtrue = 0; duint brfalse = 0; duint icount = 0; bool terminal = false; bool split = false; bool indirectcall = false; void* userdata = nullptr; std::vector<duint> exits; std::vector<BridgeCFInstruction> instrs;
static void Free(const BridgeCFNodeList* nodeList)
{
if(!BridgeList<duint>::Free(&nodeList->exits))
__debugbreak();
if(!BridgeList<BridgeCFInstruction>::Free(&nodeList->instrs))
__debugbreak();
}
BridgeCFNode() = default;
BridgeCFNode(const BridgeCFNodeList* nodeList, bool freedata)
{
if(!nodeList)
__debugbreak();
parentGraph = nodeList->parentGraph;
start = nodeList->start;
end = nodeList->end;
brtrue = nodeList->brtrue;
brfalse = nodeList->brfalse;
icount = nodeList->icount;
terminal = nodeList->terminal;
indirectcall = nodeList->indirectcall;
split = nodeList->split;
userdata = nodeList->userdata;
if(!BridgeList<duint>::ToVector(&nodeList->exits, exits, freedata))
__debugbreak();
if(!BridgeList<BridgeCFInstruction>::ToVector(&nodeList->instrs, instrs, freedata))
__debugbreak();
}
BridgeCFNode(duint parentGraph, duint start, duint end)
: parentGraph(parentGraph),
start(start),
end(end)
{
}
BridgeCFNodeList ToNodeList() const
{
BridgeCFNodeList out;
out.parentGraph = parentGraph;
out.start = start;
out.end = end;
out.brtrue = brtrue;
out.brfalse = brfalse;
out.icount = icount;
out.terminal = terminal;
out.indirectcall = indirectcall;
out.split = split;
out.userdata = userdata;
BridgeList<duint>::CopyData(&out.exits, exits);
BridgeList<BridgeCFInstruction>::CopyData(&out.instrs, instrs);
return std::move(out);
}
};
struct BridgeCFGraph
{
duint entryPoint; void* userdata; std::unordered_map<duint, BridgeCFNode> nodes; std::unordered_map<duint, std::unordered_set<duint>> parents;
static void Free(const BridgeCFGraphList* graphList)
{
if(!graphList || graphList->nodes.size != graphList->nodes.count * sizeof(BridgeCFNodeList))
__debugbreak();
auto data = (BridgeCFNodeList*)graphList->nodes.data;
for(int i = 0; i < graphList->nodes.count; i++)
BridgeCFNode::Free(&data[i]);
BridgeFree(data);
}
explicit BridgeCFGraph(const BridgeCFGraphList* graphList, bool freedata)
{
if(!graphList || graphList->nodes.size != graphList->nodes.count * sizeof(BridgeCFNodeList))
__debugbreak();
entryPoint = graphList->entryPoint;
userdata = graphList->userdata;
auto data = (BridgeCFNodeList*)graphList->nodes.data;
for(int i = 0; i < graphList->nodes.count; i++)
AddNode(BridgeCFNode(&data[i], freedata));
if(freedata && data)
BridgeFree(data);
}
explicit BridgeCFGraph(duint entryPoint)
: entryPoint(entryPoint),
userdata(nullptr)
{
}
void AddNode(const BridgeCFNode & node)
{
nodes[node.start] = node;
AddParent(node.start, node.brtrue);
AddParent(node.start, node.brfalse);
}
void AddParent(duint child, duint parent)
{
if(!child || !parent)
return;
auto found = parents.find(child);
if(found == parents.end())
{
parents[child] = std::unordered_set<duint>();
parents[child].insert(parent);
}
else
found->second.insert(parent);
}
BridgeCFGraphList ToGraphList() const
{
BridgeCFGraphList out;
out.entryPoint = entryPoint;
out.userdata = userdata;
std::vector<BridgeCFNodeList> nodeList;
nodeList.reserve(nodes.size());
for(const auto & nodeIt : nodes)
nodeList.push_back(nodeIt.second.ToNodeList());
BridgeList<BridgeCFNodeList>::CopyData(&out.nodes, nodeList);
return std::move(out);
}
};
#endif #endif
#endif