From bfa6fce83383e7be1458a917f8e6dbf71bdab28b Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 4 Jun 2018 14:12:26 -0400 Subject: Generic flow graph API and report collections --- binaryninjaapi.h | 104 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 74 insertions(+), 30 deletions(-) (limited to 'binaryninjaapi.h') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 05c8c4e3..3582b265 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -494,6 +494,8 @@ namespace BinaryNinja class MainThreadActionHandler; class InteractionHandler; class QualifiedName; + class FlowGraph; + class ReportCollection; struct FormInputField; /*! Logs to the error console with the given BNLogLevel. @@ -627,6 +629,8 @@ namespace BinaryNinja const std::string& plainText = ""); void ShowHTMLReport(const std::string& title, const std::string& contents, const std::string& plainText = ""); + void ShowGraphReport(const std::string& title, FlowGraph* graph); + void ShowReportCollection(const std::string& title, ReportCollection* reports); bool GetTextLineInput(std::string& result, const std::string& prompt, const std::string& title); bool GetIntegerInput(int64_t& result, const std::string& prompt, const std::string& title); @@ -988,6 +992,9 @@ namespace BinaryNinja uint64_t addr; size_t instrIndex; std::vector tokens; + BNHighlightColor highlight; + + DisassemblyTextLine(); }; struct LinearDisassemblyPosition @@ -1313,6 +1320,7 @@ namespace BinaryNinja void ShowPlainTextReport(const std::string& title, const std::string& contents); void ShowMarkdownReport(const std::string& title, const std::string& contents, const std::string& plainText); void ShowHTMLReport(const std::string& title, const std::string& contents, const std::string& plainText); + void ShowGraphReport(const std::string& title, FlowGraph* graph); bool GetAddressInput(uint64_t& result, const std::string& prompt, const std::string& title); bool GetAddressInput(uint64_t& result, const std::string& prompt, const std::string& title, uint64_t currentAddress); @@ -2327,7 +2335,7 @@ namespace BinaryNinja static PossibleValueSet FromAPIObject(BNPossibleValueSet& value); }; - class FunctionGraph; + class FlowGraph; class MediumLevelILFunction; class Function: public CoreRefCountObject @@ -2338,6 +2346,7 @@ namespace BinaryNinja Function(BNFunction* func); virtual ~Function(); + Ref GetView() const; Ref GetArchitecture() const; Ref GetPlatform() const; uint64_t GetStart() const; @@ -2415,7 +2424,7 @@ namespace BinaryNinja void ApplyImportedTypes(Symbol* sym); void ApplyAutoDiscoveredType(Type* type); - Ref CreateFunctionGraph(); + Ref CreateFunctionGraph(BNFunctionGraphType type, DisassemblySettings* settings = nullptr); std::map> GetStackLayout(); void CreateAutoStackVariable(int64_t offset, const Confidence>& type, const std::string& name); @@ -2495,6 +2504,8 @@ namespace BinaryNinja bool IsAnalysisSkipped(); BNFunctionAnalysisSkipOverride GetAnalysisSkipOverride(); void SetAnalysisSkipOverride(BNFunctionAnalysisSkipOverride skip); + + Ref GetUnresolvedStackAdjustmentGraph(); }; class AdvancedFunctionAnalysisDataRequestor @@ -2511,79 +2522,87 @@ namespace BinaryNinja void SetFunction(Function* func); }; - struct FunctionGraphEdge + class FlowGraphNode; + + struct FlowGraphEdge { BNBranchType type; - Ref target; + Ref target; std::vector points; bool backEdge; }; - class FunctionGraphBlock: public CoreRefCountObject + class FlowGraphNode: public CoreRefCountObject { std::vector m_cachedLines; - std::vector m_cachedEdges; + std::vector m_cachedEdges; bool m_cachedLinesValid, m_cachedEdgesValid; public: - FunctionGraphBlock(BNFunctionGraphBlock* block); + FlowGraphNode(FlowGraph* graph); + FlowGraphNode(BNFlowGraphNode* node); Ref GetBasicBlock() const; - Ref GetArchitecture() const; - uint64_t GetStart() const; - uint64_t GetEnd() const; + void SetBasicBlock(BasicBlock* block); int GetX() const; int GetY() const; int GetWidth() const; int GetHeight() const; const std::vector& GetLines(); - const std::vector& GetOutgoingEdges(); + void SetLines(const std::vector& lines); + const std::vector& GetOutgoingEdges(); + void AddOutgoingEdge(BNBranchType type, FlowGraphNode* target); + + BNHighlightColor GetHighlight() const; + void SetHighlight(const BNHighlightColor& color); }; - class FunctionGraph: public RefCountObject + class FlowGraph: public RefCountObject { - BNFunctionGraph* m_graph; + BNFlowGraph* m_graph; std::function m_completeFunc; - std::map> m_cachedBlocks; + std::map> m_cachedNodes; static void CompleteCallback(void* ctxt); public: - FunctionGraph(BNFunctionGraph* graph); - ~FunctionGraph(); + FlowGraph(BNFlowGraph* graph); + ~FlowGraph(); - BNFunctionGraph* GetGraphObject() const { return m_graph; } + BNFlowGraph* GetGraphObject() const { return m_graph; } Ref GetFunction() const; + void SetFunction(Function* func); - int GetHorizontalBlockMargin() const; - int GetVerticalBlockMargin() const; - void SetBlockMargins(int horiz, int vert); - - Ref GetSettings(); + int GetHorizontalNodeMargin() const; + int GetVerticalNodeMargin() const; + void SetNodeMargins(int horiz, int vert); - void StartLayout(BNFunctionGraphType = NormalFunctionGraph); + void StartLayout(); bool IsLayoutComplete(); void OnComplete(const std::function& func); void Abort(); - std::vector> GetBlocks(); - bool HasBlocks() const; + std::vector> GetNodes(); + Ref GetNode(size_t i); + bool HasNodes() const; + size_t AddNode(FlowGraphNode* node); int GetWidth() const; int GetHeight() const; - std::vector> GetBlocksInRegion(int left, int top, int right, int bottom); - - bool IsOptionSet(BNDisassemblyOption option) const; - void SetOption(BNDisassemblyOption option, bool state = true); + std::vector> GetNodesInRegion(int left, int top, int right, int bottom); bool IsILGraph() const; bool IsLowLevelILGraph() const; bool IsMediumLevelILGraph() const; Ref GetLowLevelILFunction() const; Ref GetMediumLevelILFunction() const; + void SetLowLevelILFunction(LowLevelILFunction* func); + void SetMediumLevelILFunction(MediumLevelILFunction* func); + + void Show(const std::string& title); }; struct LowLevelILLabel: public BNLowLevelILLabel @@ -3776,6 +3795,29 @@ namespace BinaryNinja static FormInputField DirectoryName(const std::string& prompt, const std::string& defaultName = ""); }; + class ReportCollection: public CoreRefCountObject + { + public: + ReportCollection(); + ReportCollection(BNReportCollection* reports); + + size_t GetCount() const; + BNReportType GetType(size_t i) const; + Ref GetView(size_t i) const; + std::string GetTitle(size_t i) const; + std::string GetContents(size_t i) const; + std::string GetPlainText(size_t i) const; + Ref GetFlowGraph(size_t i) const; + + void AddPlainTextReport(Ref view, const std::string& title, const std::string& contents); + void AddMarkdownReport(Ref view, const std::string& title, const std::string& contents, + const std::string& plainText = ""); + void AddHTMLReport(Ref view, const std::string& title, const std::string& contents, + const std::string& plainText = ""); + void AddGraphReport(Ref view, const std::string& title, Ref graph); + }; + class InteractionHandler { public: @@ -3784,6 +3826,8 @@ namespace BinaryNinja const std::string& plainText); virtual void ShowHTMLReport(Ref view, const std::string& title, const std::string& contents, const std::string& plainText); + virtual void ShowGraphReport(Ref view, const std::string& title, Ref graph); + virtual void ShowReportCollection(const std::string& title, Ref reports); virtual bool GetTextLineInput(std::string& result, const std::string& prompt, const std::string& title) = 0; virtual bool GetIntegerInput(int64_t& result, const std::string& prompt, const std::string& title); -- cgit v1.3.1 From dfe5d28f0aaee75ccad8c733e23879676ed77c37 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Wed, 11 Jul 2018 20:32:22 -0400 Subject: Add APIs for subclassing flow graphs --- binaryninjaapi.h | 38 +++++++++++++++++++++++++++++++------ binaryninjacore.h | 11 +++++++++++ flowgraph.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++ python/flowgraph.py | 40 ++++++++++++++++++++++++++++++++++++--- 4 files changed, 134 insertions(+), 9 deletions(-) (limited to 'binaryninjaapi.h') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 3582b265..1133625e 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -54,6 +54,7 @@ namespace BinaryNinja virtual ~RefCountObject() {} RefCountObject* GetObject() { return this; } + static RefCountObject* GetObject(RefCountObject* obj) { return obj; } void AddRef() { @@ -107,6 +108,13 @@ namespace BinaryNinja T* GetObject() const { return m_object; } + static T* GetObject(CoreRefCountObject* obj) + { + if (!obj) + return nullptr; + return obj->GetObject(); + } + void AddRef() { if (m_object && (m_refs != 0)) @@ -164,6 +172,13 @@ namespace BinaryNinja T* GetObject() const { return m_object; } + static T* GetObject(StaticCoreRefCountObject* obj) + { + if (!obj) + return nullptr; + return obj->GetObject(); + } + void AddRef() { AddRefInternal(); @@ -252,32 +267,32 @@ namespace BinaryNinja bool operator==(const T* obj) const { - return m_obj->GetObject() == obj->GetObject(); + return T::GetObject(m_obj) == T::GetObject(obj); } bool operator==(const Ref& obj) const { - return m_obj->GetObject() == obj.m_obj->GetObject(); + return T::GetObject(m_obj) == T::GetObject(obj.m_obj); } bool operator!=(const T* obj) const { - return m_obj->GetObject() != obj->GetObject(); + return T::GetObject(m_obj) != T::GetObject(obj); } bool operator!=(const Ref& obj) const { - return m_obj->GetObject() != obj.m_obj->GetObject(); + return T::GetObject(m_obj) != T::GetObject(obj.m_obj); } bool operator<(const T* obj) const { - return m_obj->GetObject() < obj->GetObject(); + return T::GetObject(m_obj) < T::GetObject(obj); } bool operator<(const Ref& obj) const { - return m_obj->GetObject() < obj.m_obj->GetObject(); + return T::GetObject(m_obj) < T::GetObject(obj.m_obj); } T* GetPtr() const @@ -2567,7 +2582,18 @@ namespace BinaryNinja static void CompleteCallback(void* ctxt); + static void PrepareForLayoutCallback(void* ctxt); + static void PopulateNodesCallback(void* ctxt); + static void CompleteLayoutCallback(void* ctxt); + + protected: + void FinishPrepareForLayout(); + virtual void PrepareForLayout(); + virtual void PopulateNodes(); + virtual void CompleteLayout(); + public: + FlowGraph(); FlowGraph(BNFlowGraph* graph); ~FlowGraph(); diff --git a/binaryninjacore.h b/binaryninjacore.h index c057b378..a32d8364 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1772,6 +1772,14 @@ extern "C" FlowGraphReportType }; + struct BNCustomFlowGraph + { + void* context; + void (*prepareForLayout)(void* ctxt); + void (*populateNodes)(void* ctxt); + void (*completeLayout)(void* ctxt); + }; + BINARYNINJACOREAPI char* BNAllocString(const char* contents); BINARYNINJACOREAPI void BNFreeString(char* str); BINARYNINJACOREAPI char** BNAllocStringList(const char** contents, size_t size); @@ -2566,6 +2574,7 @@ extern "C" BINARYNINJACOREAPI BNFlowGraph* BNCreateFlowGraph(); BINARYNINJACOREAPI BNFlowGraph* BNCreateFunctionGraph(BNFunction* func, BNFunctionGraphType type, BNDisassemblySettings* settings); + BINARYNINJACOREAPI BNFlowGraph* BNCreateCustomFlowGraph(BNCustomFlowGraph* callbacks); BINARYNINJACOREAPI BNFlowGraph* BNNewFlowGraphReference(BNFlowGraph* graph); BINARYNINJACOREAPI void BNFreeFlowGraph(BNFlowGraph* graph); BINARYNINJACOREAPI BNFunction* BNGetFunctionForFlowGraph(BNFlowGraph* graph); @@ -2618,6 +2627,8 @@ extern "C" BINARYNINJACOREAPI BNHighlightColor BNGetFlowGraphNodeHighlight(BNFlowGraphNode* node); BINARYNINJACOREAPI void BNSetFlowGraphNodeHighlight(BNFlowGraphNode* node, BNHighlightColor color); + BINARYNINJACOREAPI void BNFinishPrepareForLayout(BNFlowGraph* graph); + // Symbols BINARYNINJACOREAPI BNSymbol* BNCreateSymbol(BNSymbolType type, const char* shortName, const char* fullName, const char* rawName, uint64_t addr); diff --git a/flowgraph.cpp b/flowgraph.cpp index e557f540..4bacee81 100644 --- a/flowgraph.cpp +++ b/flowgraph.cpp @@ -24,6 +24,17 @@ using namespace BinaryNinja; using namespace std; +FlowGraph::FlowGraph() +{ + BNCustomFlowGraph callbacks; + callbacks.context = this; + callbacks.prepareForLayout = PrepareForLayoutCallback; + callbacks.populateNodes = PopulateNodesCallback; + callbacks.completeLayout = CompleteLayoutCallback; + m_graph = BNCreateCustomFlowGraph(&callbacks); +} + + FlowGraph::FlowGraph(BNFlowGraph* graph): m_graph(graph) { } @@ -46,6 +57,49 @@ void FlowGraph::CompleteCallback(void* ctxt) } +void FlowGraph::PrepareForLayoutCallback(void* ctxt) +{ + FlowGraph* graph = (FlowGraph*)ctxt; + graph->PrepareForLayout(); +} + + +void FlowGraph::PopulateNodesCallback(void* ctxt) +{ + FlowGraph* graph = (FlowGraph*)ctxt; + graph->PopulateNodes(); +} + + +void FlowGraph::CompleteLayoutCallback(void* ctxt) +{ + FlowGraph* graph = (FlowGraph*)ctxt; + graph->CompleteLayout(); +} + + +void FlowGraph::FinishPrepareForLayout() +{ + BNFinishPrepareForLayout(m_graph); +} + + +void FlowGraph::PrepareForLayout() +{ + FinishPrepareForLayout(); +} + + +void FlowGraph::PopulateNodes() +{ +} + + +void FlowGraph::CompleteLayout() +{ +} + + Ref FlowGraph::GetFunction() const { BNFunction* func = BNGetFunctionForFlowGraph(m_graph); diff --git a/python/flowgraph.py b/python/flowgraph.py index 1568bc77..25fdc430 100644 --- a/python/flowgraph.py +++ b/python/flowgraph.py @@ -24,13 +24,12 @@ import traceback # Binary Ninja components import _binaryninjacore as core -from enums import (BranchType, InstructionTextTokenType, HighlightColorStyle, HighlightStandardColor) +from enums import (BranchType, InstructionTextTokenType, HighlightStandardColor) import function import binaryview import lowlevelil import mediumlevelil import basicblock -import architecture import log import interaction import highlight @@ -264,7 +263,12 @@ class FlowGraphNode(object): class FlowGraph(object): def __init__(self, handle = None): if handle is None: - handle = core.BNCreateFlowGraph() + self._ext_cb = core.BNCustomFlowGraph() + self._ext_cb.context = 0 + self._ext_cb.prepareForLayout = self._ext_cb.prepareForLayout.__class__(self._prepare_for_layout) + self._ext_cb.populateNodes = self._ext_cb.populateNodes.__class__(self._populate_nodes) + self._ext_cb.completeLayout = self._ext_cb.completeLayout.__class__(self._complete_layout) + handle = core.BNCreateCustomFlowGraph(self._ext_cb) self.handle = handle self._on_complete = None self._cb = ctypes.CFUNCTYPE(None, ctypes.c_void_p)(self._complete) @@ -283,6 +287,36 @@ class FlowGraph(object): return True return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + def _prepare_for_layout(self, ctxt): + try: + self.prepare_for_layout() + except: + log.log_error(traceback.format_exc()) + + def _populate_nodes(self, ctxt): + try: + self.populate_nodes() + except: + log.log_error(traceback.format_exc()) + + def _complete_layout(self, ctxt): + try: + self.complete_layout() + except: + log.log_error(traceback.format_exc()) + + def finish_prepare_for_layout(self): + core.BNFinishPrepareForLayout(self.handle) + + def prepare_for_layout(self): + self.finish_prepare_for_layout() + + def populate_nodes(self): + pass + + def complete_layout(self): + pass + @property def function(self): """Function for a flow graph""" -- cgit v1.3.1 From c5c93fc82b8929d04f62d241ca50228de60fa5f4 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Fri, 13 Jul 2018 18:43:34 -0400 Subject: Add ability to update custom flow graphs --- binaryninjaapi.h | 13 ++++++++++++- binaryninjacore.h | 3 +++ flowgraph.cpp | 30 ++++++++++++++++++++++++++++++ function.cpp | 4 ++-- interaction.cpp | 4 ++-- python/flowgraph.py | 25 +++++++++++++++++++++++++ python/function.py | 4 ++-- python/interaction.py | 4 ++-- 8 files changed, 78 insertions(+), 9 deletions(-) (limited to 'binaryninjaapi.h') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 1133625e..dd685d2b 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2585,8 +2585,11 @@ namespace BinaryNinja static void PrepareForLayoutCallback(void* ctxt); static void PopulateNodesCallback(void* ctxt); static void CompleteLayoutCallback(void* ctxt); + static BNFlowGraph* UpdateCallback(void* ctxt); protected: + FlowGraph(BNFlowGraph* graph); + void FinishPrepareForLayout(); virtual void PrepareForLayout(); virtual void PopulateNodes(); @@ -2594,7 +2597,6 @@ namespace BinaryNinja public: FlowGraph(); - FlowGraph(BNFlowGraph* graph); ~FlowGraph(); BNFlowGraph* GetGraphObject() const { return m_graph; } @@ -2629,6 +2631,15 @@ namespace BinaryNinja void SetMediumLevelILFunction(MediumLevelILFunction* func); void Show(const std::string& title); + + virtual Ref Update(); + }; + + class CoreFlowGraph: public FlowGraph + { + public: + CoreFlowGraph(BNFlowGraph* graph); + virtual Ref Update() override; }; struct LowLevelILLabel: public BNLowLevelILLabel diff --git a/binaryninjacore.h b/binaryninjacore.h index a32d8364..9359ca0e 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1778,6 +1778,7 @@ extern "C" void (*prepareForLayout)(void* ctxt); void (*populateNodes)(void* ctxt); void (*completeLayout)(void* ctxt); + BNFlowGraph* (*update)(void* ctxt); }; BINARYNINJACOREAPI char* BNAllocString(const char* contents); @@ -2629,6 +2630,8 @@ extern "C" BINARYNINJACOREAPI void BNFinishPrepareForLayout(BNFlowGraph* graph); + BINARYNINJACOREAPI BNFlowGraph* BNUpdateFlowGraph(BNFlowGraph* graph); + // Symbols BINARYNINJACOREAPI BNSymbol* BNCreateSymbol(BNSymbolType type, const char* shortName, const char* fullName, const char* rawName, uint64_t addr); diff --git a/flowgraph.cpp b/flowgraph.cpp index 4bacee81..c779db0c 100644 --- a/flowgraph.cpp +++ b/flowgraph.cpp @@ -78,6 +78,16 @@ void FlowGraph::CompleteLayoutCallback(void* ctxt) } +BNFlowGraph* FlowGraph::UpdateCallback(void* ctxt) +{ + FlowGraph* graph = (FlowGraph*)ctxt; + Ref result = graph->Update(); + if (!result) + return nullptr; + return BNNewFlowGraphReference(result->GetGraphObject()); +} + + void FlowGraph::FinishPrepareForLayout() { BNFinishPrepareForLayout(m_graph); @@ -313,3 +323,23 @@ void FlowGraph::Show(const string& title) { ShowGraphReport(title, this); } + + +Ref FlowGraph::Update() +{ + return nullptr; +} + + +CoreFlowGraph::CoreFlowGraph(BNFlowGraph* graph): FlowGraph(graph) +{ +} + + +Ref CoreFlowGraph::Update() +{ + BNFlowGraph* graph = BNUpdateFlowGraph(GetGraphObject()); + if (!graph) + return nullptr; + return new CoreFlowGraph(graph); +} diff --git a/function.cpp b/function.cpp index 62a8e1b0..202f6d77 100644 --- a/function.cpp +++ b/function.cpp @@ -811,7 +811,7 @@ void Function::ApplyAutoDiscoveredType(Type* type) Ref Function::CreateFunctionGraph(BNFunctionGraphType type, DisassemblySettings* settings) { BNFlowGraph* graph = BNCreateFunctionGraph(m_object, type, settings ? settings->GetObject() : nullptr); - return new FlowGraph(graph); + return new CoreFlowGraph(graph); } @@ -1396,7 +1396,7 @@ Ref Function::GetUnresolvedStackAdjustmentGraph() BNFlowGraph* graph = BNGetUnresolvedStackAdjustmentGraph(m_object); if (!graph) return nullptr; - return new FlowGraph(graph); + return new CoreFlowGraph(graph); } diff --git a/interaction.cpp b/interaction.cpp index 61c9dfb3..da3942bb 100644 --- a/interaction.cpp +++ b/interaction.cpp @@ -208,7 +208,7 @@ static void ShowGraphReportCallback(void* ctxt, BNBinaryView* view, const char* { InteractionHandler* handler = (InteractionHandler*)ctxt; handler->ShowGraphReport(view ? new BinaryView(BNNewViewReference(view)) : nullptr, title, - new FlowGraph(BNNewFlowGraphReference(graph))); + new CoreFlowGraph(BNNewFlowGraphReference(graph))); } @@ -663,7 +663,7 @@ Ref ReportCollection::GetFlowGraph(size_t i) const BNFlowGraph* graph = BNGetReportFlowGraph(m_object, i); if (!graph) return nullptr; - return new FlowGraph(graph); + return new CoreFlowGraph(graph); } diff --git a/python/flowgraph.py b/python/flowgraph.py index 25fdc430..e6c98597 100644 --- a/python/flowgraph.py +++ b/python/flowgraph.py @@ -268,6 +268,7 @@ class FlowGraph(object): self._ext_cb.prepareForLayout = self._ext_cb.prepareForLayout.__class__(self._prepare_for_layout) self._ext_cb.populateNodes = self._ext_cb.populateNodes.__class__(self._populate_nodes) self._ext_cb.completeLayout = self._ext_cb.completeLayout.__class__(self._complete_layout) + self._ext_cb.update = self._ext_cb.update.__class__(self._update) handle = core.BNCreateCustomFlowGraph(self._ext_cb) self.handle = handle self._on_complete = None @@ -305,6 +306,16 @@ class FlowGraph(object): except: log.log_error(traceback.format_exc()) + def _update(self, ctxt): + try: + graph = self.update() + if graph is None: + return None + return core.BNNewFlowGraphReference(graph.handle) + except: + log.log_error(traceback.format_exc()) + return None + def finish_prepare_for_layout(self): core.BNFinishPrepareForLayout(self.handle) @@ -497,3 +508,17 @@ class FlowGraph(object): def show(self, title): interaction.show_graph_report(title, self) + + def update(self): + return None + + +class CoreFlowGraph(FlowGraph): + def __init__(self, handle): + super(CoreFlowGraph, self).__init__(handle) + + def update(self): + graph = core.BNUpdateFlowGraph(self.handle) + if not graph: + return None + return CoreFlowGraph(graph) diff --git a/python/function.py b/python/function.py index dca9dda6..f64a9677 100644 --- a/python/function.py +++ b/python/function.py @@ -851,7 +851,7 @@ class Function(object): graph = core.BNGetUnresolvedStackAdjustmentGraph(self.handle) if not graph: return None - return flowgraph.FlowGraph(graph) + return flowgraph.CoreFlowGraph(graph) def __iter__(self): count = ctypes.c_ulonglong() @@ -1122,7 +1122,7 @@ class Function(object): settings_obj = settings.handle else: settings_obj = None - return flowgraph.FlowGraph(core.BNCreateFunctionGraph(self.handle, graph_type, settings_obj)) + return flowgraph.CoreFlowGraph(core.BNCreateFunctionGraph(self.handle, graph_type, settings_obj)) def apply_imported_types(self, sym): core.BNApplyImportedTypes(self.handle, sym.handle) diff --git a/python/interaction.py b/python/interaction.py index 81aeb04f..b9aa0c2a 100644 --- a/python/interaction.py +++ b/python/interaction.py @@ -302,7 +302,7 @@ class InteractionHandler(object): view = binaryview.BinaryView(handle = core.BNNewViewReference(view)) else: view = None - self.show_graph_report(view, title, flowgraph.FlowGraph(core.BNNewFlowGraphReference(graph))) + self.show_graph_report(view, title, flowgraph.CoreFlowGraph(core.BNNewFlowGraphReference(graph))) except: log.log_error(traceback.format_exc()) @@ -567,7 +567,7 @@ class ReportCollection(object): plaintext = core.BNGetReportPlainText(self.handle, i) return HTMLReport(title, contents, plaintext, view) elif report_type == ReportType.FlowGraphReportType: - graph = flowgraph.FlowGraph(core.BNGetReportFlowGraph(self.handle, i)) + graph = flowgraph.CoreFlowGraph(core.BNGetReportFlowGraph(self.handle, i)) return FlowGraphReport(title, graph, view) raise TypeError("invalid report type %s" % repr(report_type)) -- cgit v1.3.1 From 7c4025df43511852ecb86d8ab608e1da476d90de Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 2 Aug 2018 22:46:43 -0400 Subject: Add API to query if an assembly instruction is a call --- binaryninjaapi.h | 1 + binaryninjacore.h | 1 + function.cpp | 6 ++++++ python/function.py | 5 +++++ 4 files changed, 13 insertions(+) (limited to 'binaryninjaapi.h') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 53e0a30d..2c467a35 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2500,6 +2500,7 @@ namespace BinaryNinja Confidence GetCallStackAdjustment(Architecture* arch, uint64_t addr); std::map> GetCallRegisterStackAdjustment(Architecture* arch, uint64_t addr); Confidence GetCallRegisterStackAdjustment(Architecture* arch, uint64_t addr, uint32_t regStack); + bool IsCallInstruction(Architecture* arch, uint64_t addr); std::vector> GetBlockAnnotations(Architecture* arch, uint64_t addr); diff --git a/binaryninjacore.h b/binaryninjacore.h index a26d1fe6..3e060c61 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2521,6 +2521,7 @@ extern "C" BNArchitecture* arch, uint64_t addr, size_t* count); BINARYNINJACOREAPI BNRegisterStackAdjustment BNGetCallRegisterStackAdjustmentForRegisterStack(BNFunction* func, BNArchitecture* arch, uint64_t addr, uint32_t regStack); + BINARYNINJACOREAPI bool BNIsCallInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI BNInstructionTextLine* BNGetFunctionBlockAnnotations(BNFunction* func, BNArchitecture* arch, uint64_t addr, size_t* count); diff --git a/function.cpp b/function.cpp index ae6d3a6b..1236cec6 100644 --- a/function.cpp +++ b/function.cpp @@ -1116,6 +1116,12 @@ Confidence Function::GetCallRegisterStackAdjustment(Architecture* arch, } +bool Function::IsCallInstruction(Architecture* arch, uint64_t addr) +{ + return BNIsCallInstruction(m_object, arch->GetObject(), addr); +} + + vector> Function::GetBlockAnnotations(Architecture* arch, uint64_t addr) { size_t count; diff --git a/python/function.py b/python/function.py index e840dd5e..64aea87f 100644 --- a/python/function.py +++ b/python/function.py @@ -1586,6 +1586,11 @@ class Function(object): result = types.RegisterStackAdjustmentWithConfidence(adjust.adjustment, confidence = adjust.confidence) return result + def is_call_instruction(self, addr, arch=None): + if arch is None: + arch = self.arch + return core.BNIsCallInstruction(self.handle, arch.handle, addr) + class AdvancedFunctionAnalysisDataRequestor(object): def __init__(self, func = None): -- cgit v1.3.1 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 --- binaryninjaapi.h | 27 +++++++---- binaryninjacore.h | 10 ++-- binaryview.cpp | 2 +- flowgraph.cpp | 128 +++++++++++++++++++++++++++----------------------- flowgraphnode.cpp | 2 +- interaction.cpp | 6 +-- python/flowgraph.py | 59 ++++++++++++++--------- python/interaction.py | 2 +- 8 files changed, 137 insertions(+), 99 deletions(-) (limited to 'binaryninjaapi.h') 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 m_completeFunc; - std::map> m_cachedNodes; static void CompleteCallback(void* ctxt); + public: + FlowGraphLayoutRequest(FlowGraph* graph, const std::function& completeFunc); + virtual ~FlowGraphLayoutRequest(); + + BNFlowGraphLayoutRequest* GetObject() const { return m_object; } + + Ref GetGraph() const; + bool IsComplete() const; + void Abort(); + }; + + class FlowGraph: public CoreRefCountObject + { + std::map> 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 GetFunction() const; void SetFunction(Function* func); @@ -2632,10 +2643,8 @@ namespace BinaryNinja int GetVerticalNodeMargin() const; void SetNodeMargins(int horiz, int vert); - void StartLayout(); + Ref StartLayout(const std::function& func); bool IsLayoutComplete(); - void OnComplete(const std::function& func); - void Abort(); std::vector> GetNodes(); Ref 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& 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); 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 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 view, const string& title, void ReportCollection::AddGraphReport(Ref view, const string& title, Ref 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 -- cgit v1.3.1 From 8e320c4be695cd47ae93673320d525ce513cec90 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Fri, 17 Aug 2018 22:11:20 -0400 Subject: Fix report collection reference count bug and add debug report support --- binaryninjaapi.h | 2 ++ binaryninjacore.h | 2 ++ function.cpp | 6 ++++++ interaction.cpp | 2 +- python/function.py | 4 ++++ 5 files changed, 15 insertions(+), 1 deletion(-) (limited to 'binaryninjaapi.h') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 67d2f7f8..32ed38d2 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2545,6 +2545,8 @@ namespace BinaryNinja void SetAnalysisSkipOverride(BNFunctionAnalysisSkipOverride skip); Ref GetUnresolvedStackAdjustmentGraph(); + + void RequestDebugReport(const std::string& name); }; class AdvancedFunctionAnalysisDataRequestor diff --git a/binaryninjacore.h b/binaryninjacore.h index 7e353ff0..c8fb9f8f 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2626,6 +2626,8 @@ extern "C" BINARYNINJACOREAPI BNFlowGraph* BNGetUnresolvedStackAdjustmentGraph(BNFunction* func); + BINARYNINJACOREAPI void BNRequestFunctionDebugReport(BNFunction* func, const char* name); + // Disassembly settings BINARYNINJACOREAPI BNDisassemblySettings* BNCreateDisassemblySettings(void); BINARYNINJACOREAPI BNDisassemblySettings* BNNewDisassemblySettingsReference(BNDisassemblySettings* settings); diff --git a/function.cpp b/function.cpp index 1236cec6..35fe4123 100644 --- a/function.cpp +++ b/function.cpp @@ -1412,6 +1412,12 @@ Ref Function::GetUnresolvedStackAdjustmentGraph() } +void Function::RequestDebugReport(const string& name) +{ + BNRequestFunctionDebugReport(m_object, name.c_str()); +} + + AdvancedFunctionAnalysisDataRequestor::AdvancedFunctionAnalysisDataRequestor(Function* func): m_func(func) { if (m_func) diff --git a/interaction.cpp b/interaction.cpp index b2e62482..5650f629 100644 --- a/interaction.cpp +++ b/interaction.cpp @@ -215,7 +215,7 @@ static void ShowGraphReportCallback(void* ctxt, BNBinaryView* view, const char* static void ShowReportCollectionCallback(void* ctxt, const char* title, BNReportCollection* reports) { InteractionHandler* handler = (InteractionHandler*)ctxt; - handler->ShowReportCollection(title, new ReportCollection(reports)); + handler->ShowReportCollection(title, new ReportCollection(BNNewReportCollectionReference(reports))); } diff --git a/python/function.py b/python/function.py index 64aea87f..295eec7e 100644 --- a/python/function.py +++ b/python/function.py @@ -1591,6 +1591,10 @@ class Function(object): arch = self.arch return core.BNIsCallInstruction(self.handle, arch.handle, addr) + def request_debug_report(self, name): + core.BNRequestFunctionDebugReport(self.handle, name) + self.view.update_analysis() + class AdvancedFunctionAnalysisDataRequestor(object): def __init__(self, func = None): -- cgit v1.3.1 From 5841af2db8e8dcf4e0da0c438ac040c5fa90038b Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 21 Aug 2018 15:47:34 -0400 Subject: Add return hint MLIL instruction (used in intermediate stages, not emitted in final forms) --- binaryninjaapi.h | 1 + binaryninjacore.h | 1 + mediumlevelilinstruction.cpp | 9 +++++++++ mediumlevelilinstruction.h | 4 ++++ python/mediumlevelil.py | 1 + 5 files changed, 16 insertions(+) (limited to 'binaryninjaapi.h') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 32ed38d2..e0406592 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -3187,6 +3187,7 @@ namespace BinaryNinja ExprId Jump(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); ExprId JumpTo(ExprId dest, const std::vector& targets, const ILSourceLocation& loc = ILSourceLocation()); + ExprId ReturnHint(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); ExprId Call(const std::vector& output, ExprId dest, const std::vector& params, const ILSourceLocation& loc = ILSourceLocation()); ExprId CallUntyped(const std::vector& output, ExprId dest, const std::vector& params, diff --git a/binaryninjacore.h b/binaryninjacore.h index c8fb9f8f..e029f208 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -851,6 +851,7 @@ extern "C" MLIL_LOW_PART, MLIL_JUMP, MLIL_JUMP_TO, + MLIL_RET_HINT, // Intermediate stages, does not appear in final forms MLIL_CALL, // Not valid in SSA form (see MLIL_CALL_SSA) MLIL_CALL_UNTYPED, // Not valid in SSA form (see MLIL_CALL_UNTYPED_SSA) MLIL_CALL_OUTPUT, // Only valid within MLIL_CALL, MLIL_SYSCALL, MLIL_TAILCALL family instructions diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp index 9cf82b08..93587c34 100644 --- a/mediumlevelilinstruction.cpp +++ b/mediumlevelilinstruction.cpp @@ -122,6 +122,7 @@ unordered_map> {MLIL_ADDRESS_OF_FIELD, {SourceVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, {MLIL_JUMP, {DestExprMediumLevelOperandUsage}}, {MLIL_JUMP_TO, {DestExprMediumLevelOperandUsage, TargetListMediumLevelOperandUsage}}, + {MLIL_RET_HINT, {DestExprMediumLevelOperandUsage}}, {MLIL_CALL, {OutputVariablesMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, {MLIL_CALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, @@ -1322,6 +1323,7 @@ void MediumLevelILInstruction::VisitExprs(const std::function& output, ExprId dest, const vector& params, const ILSourceLocation& loc) { diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h index b37b8832..d39ea87d 100644 --- a/mediumlevelilinstruction.h +++ b/mediumlevelilinstruction.h @@ -814,6 +814,10 @@ namespace BinaryNinja MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } MediumLevelILIndexList GetTargetList() const { return GetRawOperandAsIndexList(1); } }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } + }; template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase { diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index cfa8f900..774231ab 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -128,6 +128,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_LOW_PART: [("src", "expr")], MediumLevelILOperation.MLIL_JUMP: [("dest", "expr")], MediumLevelILOperation.MLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], + MediumLevelILOperation.MLIL_RET_HINT: [("dest", "expr")], MediumLevelILOperation.MLIL_CALL: [("output", "var_list"), ("dest", "expr"), ("params", "expr_list")], MediumLevelILOperation.MLIL_CALL_UNTYPED: [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_CALL_OUTPUT: [("dest", "var_list")], -- cgit v1.3.1 From acf28440dc4e8d805a057b6271a73e0d4e8c9e4f Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 30 Aug 2018 22:11:22 -0400 Subject: Allow negative stack offsets for functions like alloca_probe --- binaryninjaapi.h | 18 +++++++++--------- binaryninjacore.h | 22 ++++++++++++++-------- function.cpp | 36 ++++++++++++++++++------------------ lowlevelilinstruction.cpp | 6 +++--- lowlevelilinstruction.h | 6 +++--- python/function.py | 20 ++++++++++---------- python/types.py | 2 +- type.cpp | 10 +++++----- 8 files changed, 63 insertions(+), 57 deletions(-) (limited to 'binaryninjaapi.h') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index b5c2867b..722edcd3 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2111,7 +2111,7 @@ namespace BinaryNinja void SetConst(const Confidence& cnst); void SetVolatile(const Confidence& vltl); void SetTypeName(const QualifiedName& name); - Confidence GetStackAdjustment() const; + Confidence GetStackAdjustment() const; uint64_t GetElementCount() const; uint64_t GetOffset() const; @@ -2152,7 +2152,7 @@ namespace BinaryNinja static Ref FunctionType(const Confidence>& returnValue, const Confidence>& callingConvention, const std::vector& params, const Confidence& varArg = Confidence(false, 0), - const Confidence& stackAdjust = Confidence(0, 0)); + const Confidence& stackAdjust = Confidence(0, 0)); static std::string GenerateAutoTypeId(const std::string& source, const QualifiedName& name); static std::string GenerateAutoDemangledTypeId(const QualifiedName& name); @@ -2437,7 +2437,7 @@ namespace BinaryNinja Confidence> GetCallingConvention() const; Confidence> GetParameterVariables() const; Confidence HasVariableArguments() const; - Confidence GetStackAdjustment() const; + Confidence GetStackAdjustment() const; std::map> GetRegisterStackAdjustments() const; Confidence> GetClobberedRegisters() const; @@ -2448,7 +2448,7 @@ namespace BinaryNinja void SetAutoParameterVariables(const Confidence>& vars); void SetAutoHasVariableArguments(const Confidence& varArgs); void SetAutoCanReturn(const Confidence& returns); - void SetAutoStackAdjustment(const Confidence& stackAdjust); + void SetAutoStackAdjustment(const Confidence& stackAdjust); void SetAutoRegisterStackAdjustments(const std::map>& regStackAdjust); void SetAutoClobberedRegisters(const Confidence>& clobbered); @@ -2459,7 +2459,7 @@ namespace BinaryNinja void SetParameterVariables(const Confidence>& vars); void SetHasVariableArguments(const Confidence& varArgs); void SetCanReturn(const Confidence& returns); - void SetStackAdjustment(const Confidence& stackAdjust); + void SetStackAdjustment(const Confidence& stackAdjust); void SetRegisterStackAdjustments(const std::map>& regStackAdjust); void SetClobberedRegisters(const Confidence>& clobbered); @@ -2491,18 +2491,18 @@ namespace BinaryNinja std::vector GetIndirectBranches(); std::vector GetIndirectBranchesAt(Architecture* arch, uint64_t addr); - void SetAutoCallStackAdjustment(Architecture* arch, uint64_t addr, const Confidence& adjust); + void SetAutoCallStackAdjustment(Architecture* arch, uint64_t addr, const Confidence& adjust); void SetAutoCallRegisterStackAdjustment(Architecture* arch, uint64_t addr, const std::map>& adjust); void SetAutoCallRegisterStackAdjustment(Architecture* arch, uint64_t addr, uint32_t regStack, const Confidence& adjust); - void SetUserCallStackAdjustment(Architecture* arch, uint64_t addr, const Confidence& adjust); + void SetUserCallStackAdjustment(Architecture* arch, uint64_t addr, const Confidence& adjust); void SetUserCallRegisterStackAdjustment(Architecture* arch, uint64_t addr, const std::map>& adjust); void SetUserCallRegisterStackAdjustment(Architecture* arch, uint64_t addr, uint32_t regStack, const Confidence& adjust); - Confidence GetCallStackAdjustment(Architecture* arch, uint64_t addr); + Confidence GetCallStackAdjustment(Architecture* arch, uint64_t addr); std::map> GetCallRegisterStackAdjustment(Architecture* arch, uint64_t addr); Confidence GetCallRegisterStackAdjustment(Architecture* arch, uint64_t addr, uint32_t regStack); bool IsCallInstruction(Architecture* arch, uint64_t addr); @@ -2875,7 +2875,7 @@ namespace BinaryNinja ExprId JumpTo(ExprId dest, const std::vector& targets, const ILSourceLocation& loc = ILSourceLocation()); ExprId Call(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); - ExprId CallStackAdjust(ExprId dest, size_t adjust, const std::map& regStackAdjust, + ExprId CallStackAdjust(ExprId dest, int64_t adjust, const std::map& regStackAdjust, const ILSourceLocation& loc = ILSourceLocation()); ExprId TailCall(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); ExprId CallSSA(const std::vector& output, ExprId dest, const std::vector& params, diff --git a/binaryninjacore.h b/binaryninjacore.h index 21b04bfa..b15ceabd 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1304,6 +1304,12 @@ extern "C" uint8_t confidence; }; + struct BNOffsetWithConfidence + { + int64_t value; + uint8_t confidence; + }; + struct BNMemberScopeWithConfidence { BNMemberScope value; @@ -2397,7 +2403,7 @@ extern "C" BINARYNINJACOREAPI BNParameterVariablesWithConfidence BNGetFunctionParameterVariables(BNFunction* func); BINARYNINJACOREAPI void BNFreeParameterVariables(BNParameterVariablesWithConfidence* vars); BINARYNINJACOREAPI BNBoolWithConfidence BNFunctionHasVariableArguments(BNFunction* func); - BINARYNINJACOREAPI BNSizeWithConfidence BNGetFunctionStackAdjustment(BNFunction* func); + BINARYNINJACOREAPI BNOffsetWithConfidence BNGetFunctionStackAdjustment(BNFunction* func); BINARYNINJACOREAPI BNRegisterStackAdjustment* BNGetFunctionRegisterStackAdjustments(BNFunction* func, size_t* count); BINARYNINJACOREAPI void BNFreeRegisterStackAdjustments(BNRegisterStackAdjustment* adjustments); BINARYNINJACOREAPI BNRegisterSetWithConfidence BNGetFunctionClobberedRegisters(BNFunction* func); @@ -2409,7 +2415,7 @@ extern "C" BINARYNINJACOREAPI void BNSetAutoFunctionParameterVariables(BNFunction* func, BNParameterVariablesWithConfidence* vars); BINARYNINJACOREAPI void BNSetAutoFunctionHasVariableArguments(BNFunction* func, BNBoolWithConfidence* varArgs); BINARYNINJACOREAPI void BNSetAutoFunctionCanReturn(BNFunction* func, BNBoolWithConfidence* returns); - BINARYNINJACOREAPI void BNSetAutoFunctionStackAdjustment(BNFunction* func, BNSizeWithConfidence* stackAdjust); + BINARYNINJACOREAPI void BNSetAutoFunctionStackAdjustment(BNFunction* func, BNOffsetWithConfidence* stackAdjust); BINARYNINJACOREAPI void BNSetAutoFunctionRegisterStackAdjustments(BNFunction* func, BNRegisterStackAdjustment* adjustments, size_t count); BINARYNINJACOREAPI void BNSetAutoFunctionClobberedRegisters(BNFunction* func, BNRegisterSetWithConfidence* regs); @@ -2420,7 +2426,7 @@ extern "C" BINARYNINJACOREAPI void BNSetUserFunctionParameterVariables(BNFunction* func, BNParameterVariablesWithConfidence* vars); BINARYNINJACOREAPI void BNSetUserFunctionHasVariableArguments(BNFunction* func, BNBoolWithConfidence* varArgs); BINARYNINJACOREAPI void BNSetUserFunctionCanReturn(BNFunction* func, BNBoolWithConfidence* returns); - BINARYNINJACOREAPI void BNSetUserFunctionStackAdjustment(BNFunction* func, BNSizeWithConfidence* stackAdjust); + BINARYNINJACOREAPI void BNSetUserFunctionStackAdjustment(BNFunction* func, BNOffsetWithConfidence* stackAdjust); BINARYNINJACOREAPI void BNSetUserFunctionRegisterStackAdjustments(BNFunction* func, BNRegisterStackAdjustment* adjustments, size_t count); BINARYNINJACOREAPI void BNSetUserFunctionClobberedRegisters(BNFunction* func, BNRegisterSetWithConfidence* regs); @@ -2513,9 +2519,9 @@ extern "C" BINARYNINJACOREAPI void BNFreeIndirectBranchList(BNIndirectBranchInfo* branches); BINARYNINJACOREAPI void BNSetAutoCallStackAdjustment(BNFunction* func, BNArchitecture* arch, uint64_t addr, - size_t adjust, uint8_t confidence); + int64_t adjust, uint8_t confidence); BINARYNINJACOREAPI void BNSetUserCallStackAdjustment(BNFunction* func, BNArchitecture* arch, uint64_t addr, - size_t adjust, uint8_t confidence); + int64_t adjust, uint8_t confidence); BINARYNINJACOREAPI void BNSetAutoCallRegisterStackAdjustment(BNFunction* func, BNArchitecture* arch, uint64_t addr, BNRegisterStackAdjustment* adjust, size_t count); BINARYNINJACOREAPI void BNSetUserCallRegisterStackAdjustment(BNFunction* func, BNArchitecture* arch, uint64_t addr, @@ -2525,7 +2531,7 @@ extern "C" BINARYNINJACOREAPI void BNSetUserCallRegisterStackAdjustmentForRegisterStack(BNFunction* func, BNArchitecture* arch, uint64_t addr, uint32_t regStack, int32_t adjust, uint8_t confidence); - BINARYNINJACOREAPI BNSizeWithConfidence BNGetCallStackAdjustment(BNFunction* func, BNArchitecture* arch, uint64_t addr); + BINARYNINJACOREAPI BNOffsetWithConfidence BNGetCallStackAdjustment(BNFunction* func, BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI BNRegisterStackAdjustment* BNGetCallRegisterStackAdjustment(BNFunction* func, BNArchitecture* arch, uint64_t addr, size_t* count); BINARYNINJACOREAPI BNRegisterStackAdjustment BNGetCallRegisterStackAdjustmentForRegisterStack(BNFunction* func, @@ -3027,7 +3033,7 @@ extern "C" BINARYNINJACOREAPI BNType* BNCreateArrayType(BNTypeWithConfidence* type, uint64_t elem); BINARYNINJACOREAPI BNType* BNCreateFunctionType(BNTypeWithConfidence* returnValue, BNCallingConventionWithConfidence* callingConvention, BNFunctionParameter* params, - size_t paramCount, BNBoolWithConfidence* varArg, BNSizeWithConfidence* stackAdjust); + size_t paramCount, BNBoolWithConfidence* varArg, BNOffsetWithConfidence* stackAdjust); BINARYNINJACOREAPI BNType* BNNewTypeReference(BNType* type); BINARYNINJACOREAPI BNType* BNDuplicateType(BNType* type); BINARYNINJACOREAPI char* BNGetTypeAndName(BNType* type, BNQualifiedName* name); @@ -3060,7 +3066,7 @@ extern "C" BINARYNINJACOREAPI void BNTypeSetMemberAccess(BNType* type, BNMemberAccessWithConfidence* access); BINARYNINJACOREAPI void BNTypeSetConst(BNType* type, BNBoolWithConfidence* cnst); BINARYNINJACOREAPI void BNTypeSetVolatile(BNType* type, BNBoolWithConfidence* vltl); - BINARYNINJACOREAPI BNSizeWithConfidence BNGetTypeStackAdjustment(BNType* type); + BINARYNINJACOREAPI BNOffsetWithConfidence BNGetTypeStackAdjustment(BNType* type); BINARYNINJACOREAPI char* BNGetTypeString(BNType* type, BNPlatform* platform); BINARYNINJACOREAPI char* BNGetTypeStringBeforeName(BNType* type, BNPlatform* platform); diff --git a/function.cpp b/function.cpp index 35fe4123..167a6285 100644 --- a/function.cpp +++ b/function.cpp @@ -538,10 +538,10 @@ Confidence Function::HasVariableArguments() const } -Confidence Function::GetStackAdjustment() const +Confidence Function::GetStackAdjustment() const { - BNSizeWithConfidence sc = BNGetFunctionStackAdjustment(m_object); - return Confidence(sc.value, sc.confidence); + BNOffsetWithConfidence oc = BNGetFunctionStackAdjustment(m_object); + return Confidence(oc.value, oc.confidence); } @@ -643,12 +643,12 @@ void Function::SetAutoCanReturn(const Confidence& returns) } -void Function::SetAutoStackAdjustment(const Confidence& stackAdjust) +void Function::SetAutoStackAdjustment(const Confidence& stackAdjust) { - BNSizeWithConfidence sc; - sc.value = stackAdjust.GetValue(); - sc.confidence = stackAdjust.GetConfidence(); - BNSetAutoFunctionStackAdjustment(m_object, &sc); + BNOffsetWithConfidence oc; + oc.value = stackAdjust.GetValue(); + oc.confidence = stackAdjust.GetConfidence(); + BNSetAutoFunctionStackAdjustment(m_object, &oc); } @@ -757,12 +757,12 @@ void Function::SetCanReturn(const Confidence& returns) } -void Function::SetStackAdjustment(const Confidence& stackAdjust) +void Function::SetStackAdjustment(const Confidence& stackAdjust) { - BNSizeWithConfidence sc; - sc.value = stackAdjust.GetValue(); - sc.confidence = stackAdjust.GetConfidence(); - BNSetUserFunctionStackAdjustment(m_object, &sc); + BNOffsetWithConfidence oc; + oc.value = stackAdjust.GetValue(); + oc.confidence = stackAdjust.GetConfidence(); + BNSetUserFunctionStackAdjustment(m_object, &oc); } @@ -1026,7 +1026,7 @@ vector Function::GetIndirectBranchesAt(Architecture* arch, u } -void Function::SetAutoCallStackAdjustment(Architecture* arch, uint64_t addr, const Confidence& adjust) +void Function::SetAutoCallStackAdjustment(Architecture* arch, uint64_t addr, const Confidence& adjust) { BNSetAutoCallStackAdjustment(m_object, arch->GetObject(), addr, adjust.GetValue(), adjust.GetConfidence()); } @@ -1057,7 +1057,7 @@ void Function::SetAutoCallRegisterStackAdjustment(Architecture* arch, uint64_t a } -void Function::SetUserCallStackAdjustment(Architecture* arch, uint64_t addr, const Confidence& adjust) +void Function::SetUserCallStackAdjustment(Architecture* arch, uint64_t addr, const Confidence& adjust) { BNSetUserCallStackAdjustment(m_object, arch->GetObject(), addr, adjust.GetValue(), adjust.GetConfidence()); } @@ -1088,10 +1088,10 @@ void Function::SetUserCallRegisterStackAdjustment(Architecture* arch, uint64_t a } -Confidence Function::GetCallStackAdjustment(Architecture* arch, uint64_t addr) +Confidence Function::GetCallStackAdjustment(Architecture* arch, uint64_t addr) { - BNSizeWithConfidence result = BNGetCallStackAdjustment(m_object, arch->GetObject(), addr); - return Confidence(result.value, result.confidence); + BNOffsetWithConfidence result = BNGetCallStackAdjustment(m_object, arch->GetObject(), addr); + return Confidence(result.value, result.confidence); } diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index 5f5dc397..9ceef260 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -2498,11 +2498,11 @@ int64_t LowLevelILInstruction::GetVector() const } -size_t LowLevelILInstruction::GetStackAdjustment() const +int64_t LowLevelILInstruction::GetStackAdjustment() const { size_t operandIndex; if (GetOperandIndexForUsage(StackAdjustmentLowLevelOperandUsage, operandIndex)) - return (size_t)GetRawOperandAsInteger(operandIndex); + return GetRawOperandAsInteger(operandIndex); throw LowLevelILInstructionAccessException(); } @@ -3163,7 +3163,7 @@ ExprId LowLevelILFunction::Call(ExprId dest, const ILSourceLocation& loc) } -ExprId LowLevelILFunction::CallStackAdjust(ExprId dest, size_t adjust, +ExprId LowLevelILFunction::CallStackAdjust(ExprId dest, int64_t adjust, const std::map& regStackAdjust, const ILSourceLocation& loc) { vector list; diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h index e845bcd0..365575f8 100644 --- a/lowlevelilinstruction.h +++ b/lowlevelilinstruction.h @@ -712,7 +712,7 @@ namespace BinaryNinja template uint32_t GetIntrinsic() const { return As().GetIntrinsic(); } template int64_t GetConstant() const { return As().GetConstant(); } template int64_t GetVector() const { return As().GetVector(); } - template size_t GetStackAdjustment() const { return As().GetStackAdjustment(); } + template int64_t GetStackAdjustment() const { return As().GetStackAdjustment(); } template size_t GetTarget() const { return As().GetTarget(); } template size_t GetTrueTarget() const { return As().GetTrueTarget(); } template size_t GetFalseTarget() const { return As().GetFalseTarget(); } @@ -776,7 +776,7 @@ namespace BinaryNinja uint32_t GetIntrinsic() const; int64_t GetConstant() const; int64_t GetVector() const; - size_t GetStackAdjustment() const; + int64_t GetStackAdjustment() const; size_t GetTarget() const; size_t GetTrueTarget() const; size_t GetFalseTarget() const; @@ -1104,7 +1104,7 @@ namespace BinaryNinja template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase { LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } - size_t GetStackAdjustment() const { return (size_t)GetRawOperandAsInteger(1); } + int64_t GetStackAdjustment() const { return GetRawOperandAsInteger(1); } std::map GetRegisterStackAdjustments() const { return GetRawOperandAsRegisterStackAdjustments(2); } }; template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase diff --git a/python/function.py b/python/function.py index 295eec7e..6da86196 100644 --- a/python/function.py +++ b/python/function.py @@ -704,13 +704,13 @@ class Function(object): @stack_adjustment.setter def stack_adjustment(self, value): - sc = core.BNSizeWithConfidence() - sc.value = int(value) + oc = core.BNOffsetWithConfidence() + oc.value = int(value) if hasattr(value, 'confidence'): - sc.confidence = value.confidence + oc.confidence = value.confidence else: - sc.confidence = types.max_confidence - core.BNSetUserFunctionStackAdjustment(self.handle, sc) + oc.confidence = types.max_confidence + core.BNSetUserFunctionStackAdjustment(self.handle, oc) @property def reg_stack_adjustments(self): @@ -1262,13 +1262,13 @@ class Function(object): core.BNSetAutoFunctionCanReturn(self.handle, bc) def set_auto_stack_adjustment(self, value): - sc = core.BNSizeWithConfidence() - sc.value = int(value) + oc = core.BNOffsetWithConfidence() + oc.value = int(value) if hasattr(value, 'confidence'): - sc.confidence = value.confidence + oc.confidence = value.confidence else: - sc.confidence = types.max_confidence - core.BNSetAutoFunctionStackAdjustment(self.handle, sc) + oc.confidence = types.max_confidence + core.BNSetAutoFunctionStackAdjustment(self.handle, oc) def set_auto_reg_stack_adjustments(self, value): adjust = (core.BNRegisterStackAdjustment * len(value))() diff --git a/python/types.py b/python/types.py index 12e7733f..b0db5f33 100644 --- a/python/types.py +++ b/python/types.py @@ -630,7 +630,7 @@ class Type(object): elif not isinstance(stack_adjust, SizeWithConfidence): stack_adjust = SizeWithConfidence(stack_adjust) - stack_adjust_conf = core.BNSizeWithConfidence() + stack_adjust_conf = core.BNOffsetWithConfidence() stack_adjust_conf.value = stack_adjust.value stack_adjust_conf.confidence = stack_adjust.confidence diff --git a/type.cpp b/type.cpp index 85961a3e..1cd52527 100644 --- a/type.cpp +++ b/type.cpp @@ -435,10 +435,10 @@ uint64_t Type::GetOffset() const } -Confidence Type::GetStackAdjustment() const +Confidence Type::GetStackAdjustment() const { - BNSizeWithConfidence result = BNGetTypeStackAdjustment(m_object); - return Confidence(result.value, result.confidence); + BNOffsetWithConfidence result = BNGetTypeStackAdjustment(m_object); + return Confidence(result.value, result.confidence); } @@ -654,7 +654,7 @@ Ref Type::ArrayType(const Confidence>& type, uint64_t elem) Ref Type::FunctionType(const Confidence>& returnValue, const Confidence>& callingConvention, const std::vector& params, const Confidence& varArg, - const Confidence& stackAdjust) + const Confidence& stackAdjust) { BNTypeWithConfidence returnValueConf; returnValueConf.type = returnValue->GetObject(); @@ -680,7 +680,7 @@ Ref Type::FunctionType(const Confidence>& returnValue, varArgConf.value = varArg.GetValue(); varArgConf.confidence = varArg.GetConfidence(); - BNSizeWithConfidence stackAdjustConf; + BNOffsetWithConfidence stackAdjustConf; stackAdjustConf.value = stackAdjust.GetValue(); stackAdjustConf.confidence = stackAdjust.GetConfidence(); -- cgit v1.3.1 From e51031010b107089dd7b5b69039ac42b856a0769 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 4 Sep 2018 20:15:18 -0400 Subject: Add API to create graphs of IL functions --- binaryninjaapi.h | 4 ++++ binaryninjacore.h | 4 ++++ lowlevelil.cpp | 7 +++++++ mediumlevelil.cpp | 7 +++++++ python/lowlevelil.py | 13 ++++++++++--- python/mediumlevelil.py | 14 +++++++++++--- 6 files changed, 43 insertions(+), 6 deletions(-) (limited to 'binaryninjaapi.h') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 722edcd3..901ea65d 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -3051,6 +3051,8 @@ namespace BinaryNinja size_t GetMediumLevelILExprIndex(size_t expr) const; size_t GetMappedMediumLevelILInstructionIndex(size_t instr) const; size_t GetMappedMediumLevelILExprIndex(size_t expr) const; + + Ref CreateFunctionGraph(DisassemblySettings* settings = nullptr); }; struct MediumLevelILLabel: public BNMediumLevelILLabel @@ -3382,6 +3384,8 @@ namespace BinaryNinja Confidence> GetExprType(size_t expr); Confidence> GetExprType(const MediumLevelILInstruction& expr); + + Ref CreateFunctionGraph(DisassemblySettings* settings = nullptr); }; class FunctionRecognizer diff --git a/binaryninjacore.h b/binaryninjacore.h index b15ceabd..0916112f 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2663,6 +2663,10 @@ extern "C" BINARYNINJACOREAPI BNFlowGraph* BNCreateFlowGraph(); BINARYNINJACOREAPI BNFlowGraph* BNCreateFunctionGraph(BNFunction* func, BNFunctionGraphType type, BNDisassemblySettings* settings); + BINARYNINJACOREAPI BNFlowGraph* BNCreateLowLevelILFunctionGraph(BNLowLevelILFunction* func, + BNDisassemblySettings* settings); + BINARYNINJACOREAPI BNFlowGraph* BNCreateMediumLevelILFunctionGraph(BNMediumLevelILFunction* func, + BNDisassemblySettings* settings); BINARYNINJACOREAPI BNFlowGraph* BNCreateCustomFlowGraph(BNCustomFlowGraph* callbacks); BINARYNINJACOREAPI BNFlowGraph* BNNewFlowGraphReference(BNFlowGraph* graph); BINARYNINJACOREAPI void BNFreeFlowGraph(BNFlowGraph* graph); diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 40748327..3e09e085 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -766,3 +766,10 @@ size_t LowLevelILFunction::GetMappedMediumLevelILExprIndex(size_t expr) const { return BNGetMappedMediumLevelILExprIndex(m_object, expr); } + + +Ref LowLevelILFunction::CreateFunctionGraph(DisassemblySettings* settings) +{ + BNFlowGraph* graph = BNCreateLowLevelILFunctionGraph(m_object, settings ? settings->GetObject() : nullptr); + return new CoreFlowGraph(graph); +} diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index cac45dd6..2d1fe904 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -738,3 +738,10 @@ Confidence> MediumLevelILFunction::GetExprType(const MediumLevelILInst { return GetExprType(expr.exprIndex); } + + +Ref MediumLevelILFunction::CreateFunctionGraph(DisassemblySettings* settings) +{ + BNFlowGraph* graph = BNCreateMediumLevelILFunctionGraph(m_object, settings ? settings->GetObject() : nullptr); + return new CoreFlowGraph(graph); +} diff --git a/python/lowlevelil.py b/python/lowlevelil.py index ec7c37fd..b2a28d6e 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -734,9 +734,9 @@ class LowLevelILFunction(object): if handle is not None: self.handle = core.handle_of_type(handle, core.BNLowLevelILFunction) else: - func_handle = None - if self.source_function is not None: - func_handle = self.source_function.handle + if self.source_function is None: + raise ValueError("IL functions must be created with an associated function") + func_handle = self.source_function.handle self.handle = core.BNCreateLowLevelILFunction(arch.handle, func_handle) def __del__(self): @@ -2354,6 +2354,13 @@ class LowLevelILFunction(object): return None return result + def create_graph(self, settings = None): + if settings is not None: + settings_obj = settings.handle + else: + settings_obj = None + return binaryninja.flowgraph.CoreFlowGraph(core.BNCreateLowLevelILFunctionGraph(self.handle, settings_obj)) + class LowLevelILBasicBlock(basicblock.BasicBlock): def __init__(self, view, handle, owner): diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index d8347ebf..a862adca 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -22,6 +22,7 @@ import ctypes import struct # Binary Ninja components +import binaryninja from binaryninja import _binaryninjacore as core from binaryninja.enums import MediumLevelILOperation, InstructionTextTokenType, ILBranchDependence from binaryninja import basicblock #required for MediumLevelILBasicBlock argument @@ -616,9 +617,9 @@ class MediumLevelILFunction(object): if handle is not None: self.handle = core.handle_of_type(handle, core.BNMediumLevelILFunction) else: - func_handle = None - if self.source_function is not None: - func_handle = self.source_function.handle + if self.source_function is None: + raise ValueError("IL functions must be created with an associated function") + func_handle = self.source_function.handle self.handle = core.BNCreateMediumLevelILFunction(arch.handle, func_handle) def __del__(self): @@ -939,6 +940,13 @@ class MediumLevelILFunction(object): return None return result + def create_graph(self, settings = None): + if settings is not None: + settings_obj = settings.handle + else: + settings_obj = None + return binaryninja.flowgraph.CoreFlowGraph(core.BNCreateMediumLevelILFunctionGraph(self.handle, settings_obj)) + class MediumLevelILBasicBlock(basicblock.BasicBlock): def __init__(self, view, handle, owner): -- cgit v1.3.1