From 1df50c8093bf3b949055d2670836fa1bb742fc1b Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 14 Aug 2018 19:59:58 -0400 Subject: Modify flow graph API to support multiple layout requests for a single graph --- flowgraph.cpp | 128 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 70 insertions(+), 58 deletions(-) (limited to 'flowgraph.cpp') 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& 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 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 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 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 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 FlowGraph::StartLayout(const std::function& func) { - BNStartFlowGraphLayout(m_graph); + return new FlowGraphLayoutRequest(this, func); } bool FlowGraph::IsLayoutComplete() { - return BNIsFlowGraphLayoutComplete(m_graph); -} - - -void FlowGraph::OnComplete(const std::function& 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> FlowGraph::GetNodes() { size_t count; - BNFlowGraphNode** nodes = BNGetFlowGraphNodes(m_graph, &count); + BNFlowGraphNode** nodes = BNGetFlowGraphNodes(m_object, &count); vector> result; result.reserve(count); @@ -201,7 +213,7 @@ vector> FlowGraph::GetNodes() Ref 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 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> 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> result; result.reserve(count); @@ -274,25 +286,25 @@ vector> 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 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 FlowGraph::GetLowLevelILFunction() const Ref 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 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 CoreFlowGraph::Update() { - BNFlowGraph* graph = BNUpdateFlowGraph(GetGraphObject()); + BNFlowGraph* graph = BNUpdateFlowGraph(GetObject()); if (!graph) return nullptr; return new CoreFlowGraph(graph); -- cgit v1.3.1