summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binaryninjaapi.h27
-rw-r--r--binaryninjacore.h10
-rw-r--r--binaryview.cpp2
-rw-r--r--flowgraph.cpp128
-rw-r--r--flowgraphnode.cpp2
-rw-r--r--interaction.cpp6
-rw-r--r--python/flowgraph.py59
-rw-r--r--python/interaction.py2
8 files changed, 137 insertions, 99 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 2c467a35..67d2f7f8 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -2598,14 +2598,28 @@ namespace BinaryNinja
void SetHighlight(const BNHighlightColor& color);
};
- class FlowGraph: public RefCountObject
+ class FlowGraphLayoutRequest: public RefCountObject
{
- BNFlowGraph* m_graph;
+ BNFlowGraphLayoutRequest* m_object;
std::function<void()> m_completeFunc;
- std::map<BNFlowGraphNode*, Ref<FlowGraphNode>> m_cachedNodes;
static void CompleteCallback(void* ctxt);
+ public:
+ FlowGraphLayoutRequest(FlowGraph* graph, const std::function<void()>& completeFunc);
+ virtual ~FlowGraphLayoutRequest();
+
+ BNFlowGraphLayoutRequest* GetObject() const { return m_object; }
+
+ Ref<FlowGraph> GetGraph() const;
+ bool IsComplete() const;
+ void Abort();
+ };
+
+ class FlowGraph: public CoreRefCountObject<BNFlowGraph, BNNewFlowGraphReference, BNFreeFlowGraph>
+ {
+ std::map<BNFlowGraphNode*, Ref<FlowGraphNode>> m_cachedNodes;
+
static void PrepareForLayoutCallback(void* ctxt);
static void PopulateNodesCallback(void* ctxt);
static void CompleteLayoutCallback(void* ctxt);
@@ -2621,9 +2635,6 @@ namespace BinaryNinja
public:
FlowGraph();
- ~FlowGraph();
-
- BNFlowGraph* GetGraphObject() const { return m_graph; }
Ref<Function> GetFunction() const;
void SetFunction(Function* func);
@@ -2632,10 +2643,8 @@ namespace BinaryNinja
int GetVerticalNodeMargin() const;
void SetNodeMargins(int horiz, int vert);
- void StartLayout();
+ Ref<FlowGraphLayoutRequest> StartLayout(const std::function<void()>& func);
bool IsLayoutComplete();
- void OnComplete(const std::function<void()>& func);
- void Abort();
std::vector<Ref<FlowGraphNode>> GetNodes();
Ref<FlowGraphNode> GetNode(size_t i);
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 3e060c61..7e353ff0 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -124,6 +124,7 @@ extern "C"
struct BNDownloadInstance;
struct BNFlowGraph;
struct BNFlowGraphNode;
+ struct BNFlowGraphLayoutRequest;
struct BNSymbol;
struct BNTemporaryFile;
struct BNLowLevelILFunction;
@@ -2654,10 +2655,13 @@ extern "C"
BINARYNINJACOREAPI int BNGetVerticalFlowGraphNodeMargin(BNFlowGraph* graph);
BINARYNINJACOREAPI void BNSetFlowGraphNodeMargins(BNFlowGraph* graph, int horiz, int vert);
- BINARYNINJACOREAPI void BNStartFlowGraphLayout(BNFlowGraph* graph);
+ BINARYNINJACOREAPI BNFlowGraphLayoutRequest* BNStartFlowGraphLayout(BNFlowGraph* graph, void* ctxt, void (*func)(void* ctxt));
BINARYNINJACOREAPI bool BNIsFlowGraphLayoutComplete(BNFlowGraph* graph);
- BINARYNINJACOREAPI void BNSetFlowGraphCompleteCallback(BNFlowGraph* graph, void* ctxt, void (*func)(void* ctxt));
- BINARYNINJACOREAPI void BNAbortFlowGraph(BNFlowGraph* graph);
+ BINARYNINJACOREAPI BNFlowGraphLayoutRequest* BNNewFlowGraphLayoutRequestReference(BNFlowGraphLayoutRequest* layout);
+ BINARYNINJACOREAPI void BNFreeFlowGraphLayoutRequest(BNFlowGraphLayoutRequest* layout);
+ BINARYNINJACOREAPI bool BNIsFlowGraphLayoutRequestComplete(BNFlowGraphLayoutRequest* layout);
+ BINARYNINJACOREAPI BNFlowGraph* BNGetGraphForFlowGraphLayoutRequest(BNFlowGraphLayoutRequest* layout);
+ BINARYNINJACOREAPI void BNAbortFlowGraphLayoutRequest(BNFlowGraphLayoutRequest* graph);
BINARYNINJACOREAPI bool BNIsILFlowGraph(BNFlowGraph* graph);
BINARYNINJACOREAPI bool BNIsLowLevelILFlowGraph(BNFlowGraph* graph);
BINARYNINJACOREAPI bool BNIsMediumLevelILFlowGraph(BNFlowGraph* graph);
diff --git a/binaryview.cpp b/binaryview.cpp
index da516184..258b0153 100644
--- a/binaryview.cpp
+++ b/binaryview.cpp
@@ -1720,7 +1720,7 @@ void BinaryView::ShowHTMLReport(const string& title, const string& contents, con
void BinaryView::ShowGraphReport(const string& title, FlowGraph* graph)
{
- BNShowGraphReport(m_object, title.c_str(), graph->GetGraphObject());
+ BNShowGraphReport(m_object, title.c_str(), graph->GetObject());
}
diff --git a/flowgraph.cpp b/flowgraph.cpp
index 81950367..dc7e628e 100644
--- a/flowgraph.cpp
+++ b/flowgraph.cpp
@@ -24,37 +24,65 @@ using namespace BinaryNinja;
using namespace std;
-FlowGraph::FlowGraph()
+FlowGraphLayoutRequest::FlowGraphLayoutRequest(FlowGraph* graph, const std::function<void()>& completeFunc):
+ m_completeFunc(completeFunc)
{
- BNCustomFlowGraph callbacks;
- callbacks.context = this;
- callbacks.prepareForLayout = PrepareForLayoutCallback;
- callbacks.populateNodes = PopulateNodesCallback;
- callbacks.completeLayout = CompleteLayoutCallback;
- m_graph = BNCreateCustomFlowGraph(&callbacks);
+ m_object = BNStartFlowGraphLayout(graph->GetObject(), this, CompleteCallback);
}
-FlowGraph::FlowGraph(BNFlowGraph* graph): m_graph(graph)
+FlowGraphLayoutRequest::~FlowGraphLayoutRequest()
{
+ // This object is going away, so ensure that any pending completion routines are
+ // no longer called
+ Abort();
+
+ BNFreeFlowGraphLayoutRequest(m_object);
}
-FlowGraph::~FlowGraph()
+void FlowGraphLayoutRequest::CompleteCallback(void* ctxt)
{
- // This object is going away, so ensure that any pending completion routines are
- // no longer called
- if (m_completeFunc)
- Abort();
+ FlowGraphLayoutRequest* layout = (FlowGraphLayoutRequest*)ctxt;
+ layout->m_completeFunc();
+}
- BNFreeFlowGraph(m_graph);
+
+Ref<FlowGraph> FlowGraphLayoutRequest::GetGraph() const
+{
+ return new CoreFlowGraph(BNGetGraphForFlowGraphLayoutRequest(m_object));
}
-void FlowGraph::CompleteCallback(void* ctxt)
+bool FlowGraphLayoutRequest::IsComplete() const
{
- FlowGraph* graph = (FlowGraph*)ctxt;
- graph->m_completeFunc();
+ return BNIsFlowGraphLayoutRequestComplete(m_object);
+}
+
+
+void FlowGraphLayoutRequest::Abort()
+{
+ // Must clear the callback with the core before clearing our own function object, as until it
+ // is cleared in the core it can be called at any time from a different thread.
+ BNAbortFlowGraphLayoutRequest(m_object);
+ m_completeFunc = []() {};
+}
+
+
+FlowGraph::FlowGraph()
+{
+ BNCustomFlowGraph callbacks;
+ callbacks.context = this;
+ callbacks.prepareForLayout = PrepareForLayoutCallback;
+ callbacks.populateNodes = PopulateNodesCallback;
+ callbacks.completeLayout = CompleteLayoutCallback;
+ m_object = BNCreateCustomFlowGraph(&callbacks);
+}
+
+
+FlowGraph::FlowGraph(BNFlowGraph* graph)
+{
+ m_object = graph;
}
@@ -85,13 +113,13 @@ BNFlowGraph* FlowGraph::UpdateCallback(void* ctxt)
Ref<FlowGraph> result = graph->Update();
if (!result)
return nullptr;
- return BNNewFlowGraphReference(result->GetGraphObject());
+ return BNNewFlowGraphReference(result->GetObject());
}
void FlowGraph::FinishPrepareForLayout()
{
- BNFinishPrepareForLayout(m_graph);
+ BNFinishPrepareForLayout(m_object);
}
@@ -113,7 +141,7 @@ void FlowGraph::CompleteLayout()
Ref<Function> FlowGraph::GetFunction() const
{
- BNFunction* func = BNGetFunctionForFlowGraph(m_graph);
+ BNFunction* func = BNGetFunctionForFlowGraph(m_object);
if (!func)
return nullptr;
return new Function(BNNewFunctionReference(func));
@@ -122,60 +150,44 @@ Ref<Function> FlowGraph::GetFunction() const
void FlowGraph::SetFunction(Function* func)
{
- BNSetFunctionForFlowGraph(m_graph, func ? func->GetObject() : nullptr);
+ BNSetFunctionForFlowGraph(m_object, func ? func->GetObject() : nullptr);
}
int FlowGraph::GetHorizontalNodeMargin() const
{
- return BNGetHorizontalFlowGraphNodeMargin(m_graph);
+ return BNGetHorizontalFlowGraphNodeMargin(m_object);
}
int FlowGraph::GetVerticalNodeMargin() const
{
- return BNGetVerticalFlowGraphNodeMargin(m_graph);
+ return BNGetVerticalFlowGraphNodeMargin(m_object);
}
void FlowGraph::SetNodeMargins(int horiz, int vert)
{
- BNSetFlowGraphNodeMargins(m_graph, horiz, vert);
+ BNSetFlowGraphNodeMargins(m_object, horiz, vert);
}
-void FlowGraph::StartLayout()
+Ref<FlowGraphLayoutRequest> FlowGraph::StartLayout(const std::function<void()>& func)
{
- BNStartFlowGraphLayout(m_graph);
+ return new FlowGraphLayoutRequest(this, func);
}
bool FlowGraph::IsLayoutComplete()
{
- return BNIsFlowGraphLayoutComplete(m_graph);
-}
-
-
-void FlowGraph::OnComplete(const std::function<void()>& func)
-{
- m_completeFunc = func;
- BNSetFlowGraphCompleteCallback(m_graph, this, CompleteCallback);
-}
-
-
-void FlowGraph::Abort()
-{
- // Must clear the callback with the core before clearing our own function object, as until it
- // is cleared in the core it can be called at any time from a different thread.
- BNAbortFlowGraph(m_graph);
- m_completeFunc = []() {};
+ return BNIsFlowGraphLayoutComplete(m_object);
}
vector<Ref<FlowGraphNode>> FlowGraph::GetNodes()
{
size_t count;
- BNFlowGraphNode** nodes = BNGetFlowGraphNodes(m_graph, &count);
+ BNFlowGraphNode** nodes = BNGetFlowGraphNodes(m_object, &count);
vector<Ref<FlowGraphNode>> result;
result.reserve(count);
@@ -201,7 +213,7 @@ vector<Ref<FlowGraphNode>> FlowGraph::GetNodes()
Ref<FlowGraphNode> FlowGraph::GetNode(size_t i)
{
- BNFlowGraphNode* node = BNGetFlowGraphNode(m_graph, i);
+ BNFlowGraphNode* node = BNGetFlowGraphNode(m_object, i);
if (!node)
return nullptr;
@@ -222,33 +234,33 @@ Ref<FlowGraphNode> FlowGraph::GetNode(size_t i)
bool FlowGraph::HasNodes() const
{
- return BNFlowGraphHasNodes(m_graph);
+ return BNFlowGraphHasNodes(m_object);
}
size_t FlowGraph::AddNode(FlowGraphNode* node)
{
m_cachedNodes[node->GetObject()] = node;
- return BNAddFlowGraphNode(m_graph, node->GetObject());
+ return BNAddFlowGraphNode(m_object, node->GetObject());
}
int FlowGraph::GetWidth() const
{
- return BNGetFlowGraphWidth(m_graph);
+ return BNGetFlowGraphWidth(m_object);
}
int FlowGraph::GetHeight() const
{
- return BNGetFlowGraphHeight(m_graph);
+ return BNGetFlowGraphHeight(m_object);
}
vector<Ref<FlowGraphNode>> FlowGraph::GetNodesInRegion(int left, int top, int right, int bottom)
{
size_t count;
- BNFlowGraphNode** nodes = BNGetFlowGraphNodesInRegion(m_graph, left, top, right, bottom, &count);
+ BNFlowGraphNode** nodes = BNGetFlowGraphNodesInRegion(m_object, left, top, right, bottom, &count);
vector<Ref<FlowGraphNode>> result;
result.reserve(count);
@@ -274,25 +286,25 @@ vector<Ref<FlowGraphNode>> FlowGraph::GetNodesInRegion(int left, int top, int ri
bool FlowGraph::IsILGraph() const
{
- return BNIsILFlowGraph(m_graph);
+ return BNIsILFlowGraph(m_object);
}
bool FlowGraph::IsLowLevelILGraph() const
{
- return BNIsLowLevelILFlowGraph(m_graph);
+ return BNIsLowLevelILFlowGraph(m_object);
}
bool FlowGraph::IsMediumLevelILGraph() const
{
- return BNIsMediumLevelILFlowGraph(m_graph);
+ return BNIsMediumLevelILFlowGraph(m_object);
}
Ref<LowLevelILFunction> FlowGraph::GetLowLevelILFunction() const
{
- BNLowLevelILFunction* func = BNGetFlowGraphLowLevelILFunction(m_graph);
+ BNLowLevelILFunction* func = BNGetFlowGraphLowLevelILFunction(m_object);
if (!func)
return nullptr;
return new LowLevelILFunction(func);
@@ -301,7 +313,7 @@ Ref<LowLevelILFunction> FlowGraph::GetLowLevelILFunction() const
Ref<MediumLevelILFunction> FlowGraph::GetMediumLevelILFunction() const
{
- BNMediumLevelILFunction* func = BNGetFlowGraphMediumLevelILFunction(m_graph);
+ BNMediumLevelILFunction* func = BNGetFlowGraphMediumLevelILFunction(m_object);
if (!func)
return nullptr;
return new MediumLevelILFunction(func);
@@ -310,13 +322,13 @@ Ref<MediumLevelILFunction> FlowGraph::GetMediumLevelILFunction() const
void FlowGraph::SetLowLevelILFunction(LowLevelILFunction* func)
{
- BNSetFlowGraphLowLevelILFunction(m_graph, func ? func->GetObject() : nullptr);
+ BNSetFlowGraphLowLevelILFunction(m_object, func ? func->GetObject() : nullptr);
}
void FlowGraph::SetMediumLevelILFunction(MediumLevelILFunction* func)
{
- BNSetFlowGraphMediumLevelILFunction(m_graph, func ? func->GetObject() : nullptr);
+ BNSetFlowGraphMediumLevelILFunction(m_object, func ? func->GetObject() : nullptr);
}
@@ -339,7 +351,7 @@ CoreFlowGraph::CoreFlowGraph(BNFlowGraph* graph): FlowGraph(graph)
Ref<FlowGraph> CoreFlowGraph::Update()
{
- BNFlowGraph* graph = BNUpdateFlowGraph(GetGraphObject());
+ BNFlowGraph* graph = BNUpdateFlowGraph(GetObject());
if (!graph)
return nullptr;
return new CoreFlowGraph(graph);
diff --git a/flowgraphnode.cpp b/flowgraphnode.cpp
index eea033a8..60912df1 100644
--- a/flowgraphnode.cpp
+++ b/flowgraphnode.cpp
@@ -26,7 +26,7 @@ using namespace std;
FlowGraphNode::FlowGraphNode(FlowGraph* graph)
{
- m_object = BNCreateFlowGraphNode(graph->GetGraphObject());
+ m_object = BNCreateFlowGraphNode(graph->GetObject());
m_cachedLinesValid = false;
m_cachedEdgesValid = false;
}
diff --git a/interaction.cpp b/interaction.cpp
index da3942bb..b2e62482 100644
--- a/interaction.cpp
+++ b/interaction.cpp
@@ -431,9 +431,9 @@ void BinaryNinja::ShowGraphReport(const string& title, FlowGraph* graph)
{
Ref<Function> func = graph->GetFunction();
if (func)
- BNShowGraphReport(func->GetView()->GetObject(), title.c_str(), graph->GetGraphObject());
+ BNShowGraphReport(func->GetView()->GetObject(), title.c_str(), graph->GetObject());
else
- BNShowGraphReport(nullptr, title.c_str(), graph->GetGraphObject());
+ BNShowGraphReport(nullptr, title.c_str(), graph->GetObject());
}
@@ -691,5 +691,5 @@ void ReportCollection::AddHTMLReport(Ref<BinaryView> view, const string& title,
void ReportCollection::AddGraphReport(Ref<BinaryView> view, const string& title, Ref<FlowGraph> graph)
{
- BNAddGraphReportToCollection(m_object, view ? view->GetObject() : nullptr, title.c_str(), graph->GetGraphObject());
+ BNAddGraphReportToCollection(m_object, view ? view->GetObject() : nullptr, title.c_str(), graph->GetObject());
}
diff --git a/python/flowgraph.py b/python/flowgraph.py
index 884d6587..6d1174d6 100644
--- a/python/flowgraph.py
+++ b/python/flowgraph.py
@@ -263,6 +263,38 @@ class FlowGraphNode(object):
core.BNAddFlowGraphNodeOutgoingEdge(self.handle, edge_type, target.handle)
+class FlowGraphLayoutRequest(object):
+ def __init__(self, graph, callback = None):
+ self.on_complete = callback
+ self._cb = ctypes.CFUNCTYPE(None, ctypes.c_void_p)(self._complete)
+ self.handle = core.BNStartFlowGraphLayout(graph.handle, None, self._cb)
+
+ def __del__(self):
+ self.abort()
+ core.BNFreeFlowGraphLayoutRequest(self.handle)
+
+ def _complete(self, ctxt):
+ try:
+ if self._on_complete is not None:
+ self._on_complete()
+ except:
+ log.log_error(traceback.format_exc())
+
+ @property
+ def complete(self):
+ """Whether flow graph layout is complete (read-only)"""
+ return core.BNIsFlowGraphLayoutRequestComplete(self.handle)
+
+ @property
+ def graph(self):
+ """Flow graph that is being processed (read-only)"""
+ return CoreFlowGraph(core.BNGetGraphForFlowGraphLayoutRequest(self.handle))
+
+ def abort(self):
+ core.BNAbortFlowGraphLayoutRequest(self.handle)
+ self.on_complete = None
+
+
class FlowGraph(object):
def __init__(self, handle = None):
if handle is None:
@@ -274,12 +306,8 @@ class FlowGraph(object):
self._ext_cb.update = self._ext_cb.update.__class__(self._update)
handle = core.BNCreateCustomFlowGraph(self._ext_cb)
self.handle = handle
- self._on_complete = None
- self._cb = ctypes.CFUNCTYPE(None, ctypes.c_void_p)(self._complete)
def __del__(self):
- if self._on_complete is not None:
- self.abort()
core.BNFreeFlowGraph(self.handle)
def __eq__(self, value):
@@ -460,15 +488,8 @@ class FlowGraph(object):
finally:
core.BNFreeFlowGraphNodeList(nodes, count.value)
- def _complete(self, ctxt):
- try:
- if self._on_complete is not None:
- self._on_complete()
- except:
- log.log_error(traceback.format_exc())
-
- def layout(self):
- core.BNStartFlowGraphLayout(self.handle)
+ def layout(self, callback = None):
+ return FlowGraphLayoutRequest(self, callback)
def _wait_complete(self):
self._wait_cond.acquire()
@@ -477,21 +498,13 @@ class FlowGraph(object):
def layout_and_wait(self):
self._wait_cond = threading.Condition()
- self.on_complete(self._wait_complete)
- self.layout()
+ request = self.layout(self._wait_complete)
self._wait_cond.acquire()
- while not self.complete:
+ while not request.complete:
self._wait_cond.wait()
self._wait_cond.release()
- def on_complete(self, callback):
- self._on_complete = callback
- core.BNSetFlowGraphCompleteCallback(self.handle, None, self._cb)
-
- def abort(self):
- core.BNAbortFlowGraph(self.handle)
-
def get_nodes_in_region(self, left, top, right, bottom):
count = ctypes.c_ulonglong()
nodes = core.BNGetFlowGraphNodesInRegion(self.handle, left, top, right, bottom, count)
diff --git a/python/interaction.py b/python/interaction.py
index 0170e6aa..e53312cf 100644
--- a/python/interaction.py
+++ b/python/interaction.py
@@ -23,7 +23,7 @@ import traceback
# Binary Ninja components
from binaryninja import _binaryninjacore as core
-from binaryninja.enums import FormInputFieldType, MessageBoxIcon, MessageBoxButtonSet, MessageBoxButtonResult
+from binaryninja.enums import FormInputFieldType, MessageBoxIcon, MessageBoxButtonSet, MessageBoxButtonResult, ReportType
from binaryninja import binaryview
from binaryninja import log
from binaryninja import flowgraph