From 0cc77206c79257d49013c3a3ed1bf889c85b10d1 Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Sun, 14 Jan 2018 03:42:04 -0500 Subject: Container Memory Reservations. --- binaryview.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'binaryview.cpp') diff --git a/binaryview.cpp b/binaryview.cpp index 00cd294f..0ee428e1 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -670,6 +670,7 @@ vector BinaryView::GetModification(uint64_t offset, size_t len = BNGetModificationArray(m_object, offset, mod, len); vector result; + result.reserve(len); for (size_t i = 0; i < len; i++) result.push_back(mod[i]); @@ -988,6 +989,7 @@ vector> BinaryView::GetAnalysisFunctionList() BNFunction** list = BNGetAnalysisFunctionList(m_object, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Function(BNNewFunctionReference(list[i]))); @@ -1026,6 +1028,7 @@ vector> BinaryView::GetAnalysisFunctionsForAddress(uint64_t addr) BNFunction** list = BNGetAnalysisFunctionsForAddress(m_object, addr, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Function(BNNewFunctionReference(list[i]))); @@ -1058,6 +1061,7 @@ vector> BinaryView::GetBasicBlocksForAddress(uint64_t addr) BNBasicBlock** blocks = BNGetBasicBlocksForAddress(m_object, addr, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); @@ -1072,6 +1076,7 @@ vector> BinaryView::GetBasicBlocksStartingAtAddress(uint64_t add BNBasicBlock** blocks = BNGetBasicBlocksStartingAtAddress(m_object, addr, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); @@ -1086,6 +1091,7 @@ vector BinaryView::GetCodeReferences(uint64_t addr) BNReferenceSource* refs = BNGetCodeReferences(m_object, addr, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { ReferenceSource src; @@ -1106,6 +1112,7 @@ vector BinaryView::GetCodeReferences(uint64_t addr, uint64_t le BNReferenceSource* refs = BNGetCodeReferencesInRange(m_object, addr, len, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { ReferenceSource src; @@ -1144,6 +1151,7 @@ vector> BinaryView::GetSymbolsByName(const string& name) BNSymbol** syms = BNGetSymbolsByName(m_object, name.c_str(), &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); @@ -1158,6 +1166,7 @@ vector> BinaryView::GetSymbols() BNSymbol** syms = BNGetSymbols(m_object, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); @@ -1172,6 +1181,7 @@ vector> BinaryView::GetSymbols(uint64_t start, uint64_t len) BNSymbol** syms = BNGetSymbolsInRange(m_object, start, len, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); @@ -1186,6 +1196,7 @@ vector> BinaryView::GetSymbolsOfType(BNSymbolType type) BNSymbol** syms = BNGetSymbolsOfType(m_object, type, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); @@ -1200,6 +1211,7 @@ vector> BinaryView::GetSymbolsOfType(BNSymbolType type, uint64_t sta BNSymbol** syms = BNGetSymbolsOfTypeInRange(m_object, type, start, len, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); @@ -1412,6 +1424,7 @@ vector BinaryView::GetPreviousLinearDisassemblyLines(Line settings ? settings->GetObject() : nullptr, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { LinearDisassemblyLine line; @@ -1420,6 +1433,7 @@ vector BinaryView::GetPreviousLinearDisassemblyLines(Line line.block = lines[i].block ? new BasicBlock(BNNewBasicBlockReference(lines[i].block)) : nullptr; line.lineOffset = lines[i].lineOffset; line.contents.addr = lines[i].contents.addr; + line.contents.tokens.reserve(lines[i].contents.count); for (size_t j = 0; j < lines[i].contents.count; j++) { InstructionTextToken token; @@ -1458,6 +1472,7 @@ vector BinaryView::GetNextLinearDisassemblyLines(LinearDi settings ? settings->GetObject() : nullptr, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { LinearDisassemblyLine line; @@ -1466,6 +1481,7 @@ vector BinaryView::GetNextLinearDisassemblyLines(LinearDi line.block = lines[i].block ? new BasicBlock(BNNewBasicBlockReference(lines[i].block)) : nullptr; line.lineOffset = lines[i].lineOffset; line.contents.addr = lines[i].contents.addr; + line.contents.tokens.reserve(lines[i].contents.count); for (size_t j = 0; j < lines[i].contents.count; j++) { InstructionTextToken token; @@ -1704,6 +1720,7 @@ vector BinaryView::GetSegments() BNSegment* segments = BNGetSegments(m_object, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { Segment segment; @@ -1777,6 +1794,7 @@ vector
BinaryView::GetSections() BNSection* sections = BNGetSections(m_object, &count); vector
result; + result.reserve(count); for (size_t i = 0; i < count; i++) { Section section; @@ -1804,6 +1822,7 @@ vector
BinaryView::GetSectionsAt(uint64_t addr) BNSection* sections = BNGetSectionsAt(m_object, addr, &count); vector
result; + result.reserve(count); for (size_t i = 0; i < count; i++) { Section section; @@ -1855,6 +1874,7 @@ vector BinaryView::GetUniqueSectionNames(const vector& names) char** outgoingNames = BNGetUniqueSectionNames(m_object, incomingNames, names.size()); vector result; + result.reserve(names.size()); for (size_t i = 0; i < names.size(); i++) result.push_back(outgoingNames[i]); -- cgit v1.3.1 From 80a5b6d9bca0b0ef4d2a7d33b632d558d6d9b0f0 Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Mon, 22 Jan 2018 23:57:00 -0500 Subject: Add Access to Background Analysis Task. --- binaryninjaapi.h | 2 ++ binaryninjacore.h | 1 + binaryview.cpp | 10 ++++++++++ 3 files changed, 13 insertions(+) (limited to 'binaryview.cpp') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index d357e5bc..d1b6f5f5 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -486,6 +486,7 @@ namespace BinaryNinja }; class Architecture; + class BackgroundTask; class Platform; class Type; class DataBuffer; @@ -1266,6 +1267,7 @@ namespace BinaryNinja Ref AddAnalysisCompletionEvent(const std::function& callback); BNAnalysisProgress GetAnalysisProgress(); + Ref GetBackgroundAnalysisTask(); uint64_t GetNextFunctionStartAfterAddress(uint64_t addr); uint64_t GetNextBasicBlockStartAfterAddress(uint64_t addr); diff --git a/binaryninjacore.h b/binaryninjacore.h index 245e6353..e9ef7c7a 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2232,6 +2232,7 @@ extern "C" BINARYNINJACOREAPI void BNCancelAnalysisCompletionEvent(BNAnalysisCompletionEvent* event); BINARYNINJACOREAPI BNAnalysisProgress BNGetAnalysisProgress(BNBinaryView* view); + BINARYNINJACOREAPI BNBackgroundTask* BNGetBackgroundAnalysisTask(BNBinaryView* view); BINARYNINJACOREAPI uint64_t BNGetNextFunctionStartAfterAddress(BNBinaryView* view, uint64_t addr); BINARYNINJACOREAPI uint64_t BNGetNextBasicBlockStartAfterAddress(BNBinaryView* view, uint64_t addr); diff --git a/binaryview.cpp b/binaryview.cpp index 0ee428e1..96fd161d 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1351,6 +1351,16 @@ BNAnalysisProgress BinaryView::GetAnalysisProgress() } +Ref BinaryView::GetBackgroundAnalysisTask() +{ + BNBackgroundTask* task = BNGetBackgroundAnalysisTask(m_object); + if (!task) + return nullptr; + + return new BackgroundTask(BNNewBackgroundTaskReference(task)); +} + + uint64_t BinaryView::GetNextFunctionStartAfterAddress(uint64_t addr) { return BNGetNextFunctionStartAfterAddress(m_object, addr); -- cgit v1.3.1 From 1c7349fcf125994f2e577361626fe1fb02eac029 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Wed, 7 Mar 2018 18:10:55 -0500 Subject: Add APIs for skipping analysis of functions that are too large, and overriding this behavior --- binaryninjaapi.h | 11 +++++++++++ binaryninjacore.h | 17 +++++++++++++++++ binaryview.cpp | 23 +++++++++++++++++++++++ function.cpp | 24 ++++++++++++++++++++++++ functiongraph.cpp | 6 ++++++ python/binaryview.py | 19 +++++++++++++++++++ python/function.py | 34 +++++++++++++++++++++++++++++++++- 7 files changed, 133 insertions(+), 1 deletion(-) (limited to 'binaryview.cpp') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 89eba009..2d7e2ccf 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -866,6 +866,7 @@ namespace BinaryNinja static void FunctionAddedCallback(void* ctxt, BNBinaryView* data, BNFunction* func); static void FunctionRemovedCallback(void* ctxt, BNBinaryView* data, BNFunction* func); static void FunctionUpdatedCallback(void* ctxt, BNBinaryView* data, BNFunction* func); + static void FunctionUpdateRequestedCallback(void* ctxt, BNBinaryView* data, BNFunction* func); static void DataVariableAddedCallback(void* ctxt, BNBinaryView* data, BNDataVariable* var); static void DataVariableRemovedCallback(void* ctxt, BNBinaryView* data, BNDataVariable* var); static void DataVariableUpdatedCallback(void* ctxt, BNBinaryView* data, BNDataVariable* var); @@ -886,6 +887,7 @@ namespace BinaryNinja virtual void OnAnalysisFunctionAdded(BinaryView* view, Function* func) { (void)view; (void)func; } virtual void OnAnalysisFunctionRemoved(BinaryView* view, Function* func) { (void)view; (void)func; } virtual void OnAnalysisFunctionUpdated(BinaryView* view, Function* func) { (void)view; (void)func; } + virtual void OnAnalysisFunctionUpdateRequested(BinaryView* view, Function* func) { (void)view; (void)func; } virtual void OnDataVariableAdded(BinaryView* view, const DataVariable& var) { (void)view; (void)var; } virtual void OnDataVariableRemoved(BinaryView* view, const DataVariable& var) { (void)view; (void)var; } virtual void OnDataVariableUpdated(BinaryView* view, const DataVariable& var) { (void)view; (void)var; } @@ -1344,6 +1346,9 @@ namespace BinaryNinja std::string GetStringMetadata(const std::string& key); std::vector GetRawMetadata(const std::string& key); uint64_t GetUIntMetadata(const std::string& key); + + uint64_t GetMaxFunctionSizeForAnalysis(); + void SetMaxFunctionSizeForAnalysis(uint64_t size); }; class BinaryData: public BinaryView @@ -2475,6 +2480,11 @@ namespace BinaryNinja Confidence GetGlobalPointerValue() const; Confidence GetRegisterValueAtExit(uint32_t reg) const; + + bool IsFunctionTooLarge(); + bool IsAnalysisSkipped(); + BNFunctionAnalysisSkipOverride GetAnalysisSkipOverride(); + void SetAnalysisSkipOverride(BNFunctionAnalysisSkipOverride skip); }; class AdvancedFunctionAnalysisDataRequestor @@ -2550,6 +2560,7 @@ namespace BinaryNinja void Abort(); std::vector> GetBlocks(); + bool HasBlocks() const; int GetWidth() const; int GetHeight() const; diff --git a/binaryninjacore.h b/binaryninjacore.h index 5329a1d9..a1b78b1c 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -989,6 +989,7 @@ extern "C" void (*functionAdded)(void* ctxt, BNBinaryView* view, BNFunction* func); void (*functionRemoved)(void* ctxt, BNBinaryView* view, BNFunction* func); void (*functionUpdated)(void* ctxt, BNBinaryView* view, BNFunction* func); + void (*functionUpdateRequested)(void* ctxt, BNBinaryView* view, BNFunction* func); void (*dataVariableAdded)(void* ctxt, BNBinaryView* view, BNDataVariable* var); void (*dataVariableRemoved)(void* ctxt, BNBinaryView* view, BNDataVariable* var); void (*dataVariableUpdated)(void* ctxt, BNBinaryView* view, BNDataVariable* var); @@ -1739,6 +1740,13 @@ extern "C" uint8_t confidence; }; + enum BNFunctionAnalysisSkipOverride + { + DefaultFunctionAnalysisSkip, + NeverSkipFunctionAnalysis, + AlwaysSkipFunctionAnalysis + }; + BINARYNINJACOREAPI char* BNAllocString(const char* contents); BINARYNINJACOREAPI void BNFreeString(char* str); BINARYNINJACOREAPI char** BNAllocStringList(const char** contents, size_t size); @@ -2421,6 +2429,14 @@ extern "C" BINARYNINJACOREAPI void BNSetIntegerConstantDisplayType(BNFunction* func, BNArchitecture* arch, uint64_t instrAddr, uint64_t value, size_t operand, BNIntegerDisplayType type); + BINARYNINJACOREAPI bool BNIsFunctionTooLarge(BNFunction* func); + BINARYNINJACOREAPI bool BNIsFunctionAnalysisSkipped(BNFunction* func); + BINARYNINJACOREAPI BNFunctionAnalysisSkipOverride BNGetFunctionAnalysisSkipOverride(BNFunction* func); + BINARYNINJACOREAPI void BNSetFunctionAnalysisSkipOverride(BNFunction* func, BNFunctionAnalysisSkipOverride skip); + + BINARYNINJACOREAPI uint64_t BNGetMaxFunctionSizeForAnalysis(BNBinaryView* view); + BINARYNINJACOREAPI void BNSetMaxFunctionSizeForAnalysis(BNBinaryView* view, uint64_t size); + BINARYNINJACOREAPI BNAnalysisCompletionEvent* BNAddAnalysisCompletionEvent(BNBinaryView* view, void* ctxt, void (*callback)(void* ctxt)); BINARYNINJACOREAPI BNAnalysisCompletionEvent* BNNewAnalysisCompletionEventReference(BNAnalysisCompletionEvent* event); @@ -2536,6 +2552,7 @@ extern "C" BINARYNINJACOREAPI BNFunctionGraphBlock** BNGetFunctionGraphBlocksInRegion( BNFunctionGraph* graph, int left, int top, int right, int bottom, size_t* count); BINARYNINJACOREAPI void BNFreeFunctionGraphBlockList(BNFunctionGraphBlock** blocks, size_t count); + BINARYNINJACOREAPI bool BNFunctionGraphHasBlocks(BNFunctionGraph* graph); BINARYNINJACOREAPI int BNGetFunctionGraphWidth(BNFunctionGraph* graph); BINARYNINJACOREAPI int BNGetFunctionGraphHeight(BNFunctionGraph* graph); diff --git a/binaryview.cpp b/binaryview.cpp index 96fd161d..0dcf6bc3 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -78,6 +78,15 @@ void BinaryDataNotification::FunctionUpdatedCallback(void* ctxt, BNBinaryView* o } +void BinaryDataNotification::FunctionUpdateRequestedCallback(void* ctxt, BNBinaryView* object, BNFunction* func) +{ + BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; + Ref view = new BinaryView(BNNewViewReference(object)); + Ref funcObj = new Function(BNNewFunctionReference(func)); + notify->OnAnalysisFunctionUpdateRequested(view, funcObj); +} + + void BinaryDataNotification::DataVariableAddedCallback(void* ctxt, BNBinaryView* object, BNDataVariable* var) { BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; @@ -148,6 +157,7 @@ BinaryDataNotification::BinaryDataNotification() m_callbacks.functionAdded = FunctionAddedCallback; m_callbacks.functionRemoved = FunctionRemovedCallback; m_callbacks.functionUpdated = FunctionUpdatedCallback; + m_callbacks.functionUpdateRequested = FunctionUpdateRequestedCallback; m_callbacks.dataVariableAdded = DataVariableAddedCallback; m_callbacks.dataVariableRemoved = DataVariableRemovedCallback; m_callbacks.dataVariableUpdated = DataVariableUpdatedCallback; @@ -1949,6 +1959,19 @@ uint64_t BinaryView::GetUIntMetadata(const string& key) return data->GetUnsignedInteger(); } + +uint64_t BinaryView::GetMaxFunctionSizeForAnalysis() +{ + return BNGetMaxFunctionSizeForAnalysis(m_object); +} + + +void BinaryView::SetMaxFunctionSizeForAnalysis(uint64_t size) +{ + BNSetMaxFunctionSizeForAnalysis(m_object, size); +} + + BinaryData::BinaryData(FileMetadata* file): BinaryView(BNCreateBinaryDataView(file->GetObject())) { } diff --git a/function.cpp b/function.cpp index ab5f0ea3..1e91f8f3 100644 --- a/function.cpp +++ b/function.cpp @@ -1359,6 +1359,30 @@ vector Function::GetTypeTokens(DisassemblySettings* setting } +bool Function::IsFunctionTooLarge() +{ + return BNIsFunctionTooLarge(m_object); +} + + +bool Function::IsAnalysisSkipped() +{ + return BNIsFunctionAnalysisSkipped(m_object); +} + + +BNFunctionAnalysisSkipOverride Function::GetAnalysisSkipOverride() +{ + return BNGetFunctionAnalysisSkipOverride(m_object); +} + + +void Function::SetAnalysisSkipOverride(BNFunctionAnalysisSkipOverride skip) +{ + BNSetFunctionAnalysisSkipOverride(m_object, skip); +} + + AdvancedFunctionAnalysisDataRequestor::AdvancedFunctionAnalysisDataRequestor(Function* func): m_func(func) { if (m_func) diff --git a/functiongraph.cpp b/functiongraph.cpp index 77754913..a743254e 100644 --- a/functiongraph.cpp +++ b/functiongraph.cpp @@ -131,6 +131,12 @@ vector> FunctionGraph::GetBlocks() } +bool FunctionGraph::HasBlocks() const +{ + return BNFunctionGraphHasBlocks(m_graph); +} + + int FunctionGraph::GetWidth() const { return BNGetFunctionGraphWidth(m_graph); diff --git a/python/binaryview.py b/python/binaryview.py index 7a6bc875..1c986a94 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -65,6 +65,9 @@ class BinaryDataNotification(object): def function_updated(self, view, func): pass + def function_update_requested(self, view, func): + pass + def data_var_added(self, view, var): pass @@ -180,6 +183,7 @@ class BinaryDataNotificationCallbacks(object): self._cb.functionAdded = self._cb.functionAdded.__class__(self._function_added) self._cb.functionRemoved = self._cb.functionRemoved.__class__(self._function_removed) self._cb.functionUpdated = self._cb.functionUpdated.__class__(self._function_updated) + self._cb.functionUpdateRequested = self._cb.functionUpdateRequested.__class__(self._function_update_requested) self._cb.dataVariableAdded = self._cb.dataVariableAdded.__class__(self._data_var_added) self._cb.dataVariableRemoved = self._cb.dataVariableRemoved.__class__(self._data_var_removed) self._cb.dataVariableUpdated = self._cb.dataVariableUpdated.__class__(self._data_var_updated) @@ -230,6 +234,12 @@ class BinaryDataNotificationCallbacks(object): except: log.log_error(traceback.format_exc()) + def _function_update_requested(self, ctxt, view, func): + try: + self.notify.function_update_requested(self.view, function.Function(self.view, core.BNNewFunctionReference(func))) + except: + log.log_error(traceback.format_exc()) + def _data_var_added(self, ctxt, view, var): try: address = var[0].address @@ -1013,6 +1023,15 @@ class BinaryView(object): result = core.BNGetGlobalPointerValue(self.handle) return function.RegisterValue(self.arch, result.value, confidence = result.confidence) + @property + def max_function_size_for_analysis(self): + """Maximum size of function (sum of basic block sizes in bytes) for auto analysis""" + return core.BNGetMaxFunctionSizeForAnalysis(self.handle) + + @max_function_size_for_analysis.setter + def max_function_size_for_analysis(self, size): + core.BNSetMaxFunctionSizeForAnalysis(self.handle, size) + def __len__(self): return int(core.BNGetViewLength(self.handle)) diff --git a/python/function.py b/python/function.py index f68aa76f..0d796d98 100644 --- a/python/function.py +++ b/python/function.py @@ -26,7 +26,8 @@ import ctypes import _binaryninjacore as core from enums import (FunctionGraphType, BranchType, SymbolType, InstructionTextTokenType, HighlightStandardColor, HighlightColorStyle, RegisterValueType, ImplicitRegisterExtend, - DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext, VariableSourceType) + DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext, VariableSourceType, + FunctionAnalysisSkipOverride) import architecture import platform import highlight @@ -817,6 +818,32 @@ class Function(object): for i in block: yield i + @property + def too_large(self): + """Whether the function is too large to automatically perform analysis (read-only)""" + return core.BNIsFunctionTooLarge(self.handle) + + @property + def analysis_skipped(self): + """Whether automatic analysis was skipped for this function""" + return core.BNIsFunctionAnalysisSkipped(self.handle) + + @analysis_skipped.setter + def analysis_skipped(self, skip): + if skip: + core.BNSetFunctionAnalysisSkipOverride(self.handle, FunctionAnalysisSkipOverride.AlwaysSkipFunctionAnalysis) + else: + core.BNSetFunctionAnalysisSkipOverride(self.handle, FunctionAnalysisSkipOverride.NeverSkipFunctionAnalysis) + + @property + def analysis_skip_override(self): + """Override for skipping of automatic analysis""" + return FunctionAnalysisSkipOverride(core.BNGetFunctionAnalysisSkipOverride(self.handle)) + + @analysis_skip_override.setter + def analysis_skip_override(self, override): + core.BNSetFunctionAnalysisSkipOverride(self.handle, override) + def __iter__(self): count = ctypes.c_ulonglong() blocks = core.BNGetFunctionBasicBlockList(self.handle, count) @@ -1835,6 +1862,11 @@ class FunctionGraph(object): core.BNFreeFunctionGraphBlockList(blocks, count.value) return result + @property + def has_blocks(self): + """Whether the function graph has at least one block (read-only)""" + return core.BNFunctionGraphHasBlocks(self.handle) + @property def width(self): """Function graph width (read-only)""" -- cgit v1.3.1 From 7df91eab880eea11369072ae4ebc9b6ae2bb2f51 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Tue, 20 Mar 2018 17:03:18 -0400 Subject: Call CreateDatabase on parent view if it exists --- binaryview.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'binaryview.cpp') diff --git a/binaryview.cpp b/binaryview.cpp index 0dcf6bc3..8dcae40f 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -584,6 +584,9 @@ bool BinaryView::IsBackedByDatabase() const bool BinaryView::CreateDatabase(const string& path) { + auto parent = GetParentView(); + if (parent) + return parent->CreateDatabase(path); return m_file->CreateDatabase(path, this); } @@ -591,6 +594,9 @@ bool BinaryView::CreateDatabase(const string& path) bool BinaryView::CreateDatabase(const string& path, const function& progressCallback) { + auto parent = GetParentView(); + if (parent) + return parent->CreateDatabase(path); return m_file->CreateDatabase(path, this, progressCallback); } -- cgit v1.3.1 From fa716fe2da53a4f136380b1f60197bd197b2793a Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 2 Apr 2018 23:30:56 -0400 Subject: Add plugin commands for LLIL and MLIL --- basicblock.cpp | 37 +++++++++ binaryninjaapi.h | 101 ++++++++++++++++++++--- binaryninjacore.h | 69 ++++++++++++---- binaryview.cpp | 2 + function.cpp | 1 + functiongraph.cpp | 36 ++++++++ functiongraphblock.cpp | 1 + plugin.cpp | 218 ++++++++++++++++++++++++++++++++++++++++++++++++ python/basicblock.py | 21 ++++- python/function.py | 71 +++++++++++++--- python/plugin.py | 219 +++++++++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 736 insertions(+), 40 deletions(-) (limited to 'binaryview.cpp') diff --git a/basicblock.cpp b/basicblock.cpp index d42a1038..33f57d40 100644 --- a/basicblock.cpp +++ b/basicblock.cpp @@ -276,6 +276,7 @@ vector BasicBlock::GetDisassemblyText(DisassemblySettings* { DisassemblyTextLine line; line.addr = lines[i].addr; + line.instrIndex = lines[i].instrIndex; line.tokens.reserve(lines[i].count); for (size_t j = 0; j < lines[i].count; j++) { @@ -417,3 +418,39 @@ bool BasicBlock::IsBackEdge(BasicBlock* source, BasicBlock* target) } return false; } + + +bool BasicBlock::IsILBlock() const +{ + return BNIsILBasicBlock(m_object); +} + + +bool BasicBlock::IsLowLevelILBlock() const +{ + return BNIsLowLevelILBasicBlock(m_object); +} + + +bool BasicBlock::IsMediumLevelILBlock() const +{ + return BNIsMediumLevelILBasicBlock(m_object); +} + + +Ref BasicBlock::GetLowLevelILFunction() const +{ + BNLowLevelILFunction* func = BNGetBasicBlockLowLevelILFunction(m_object); + if (!func) + return nullptr; + return new LowLevelILFunction(func); +} + + +Ref BasicBlock::GetMediumLevelILFunction() const +{ + BNMediumLevelILFunction* func = BNGetBasicBlockMediumLevelILFunction(m_object); + if (!func) + return nullptr; + return new MediumLevelILFunction(func); +} diff --git a/binaryninjaapi.h b/binaryninjaapi.h index d0c19e7a..81b5105d 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -986,6 +986,7 @@ namespace BinaryNinja struct DisassemblyTextLine { uint64_t addr; + size_t instrIndex; std::vector tokens; }; @@ -1590,6 +1591,7 @@ namespace BinaryNinja }; class LowLevelILFunction; + class MediumLevelILFunction; class FunctionRecognizer; class CallingConvention; @@ -2254,6 +2256,12 @@ namespace BinaryNinja void SetUserBasicBlockHighlight(uint8_t r, uint8_t g, uint8_t b, uint8_t alpha = 255); static bool IsBackEdge(BasicBlock* source, BasicBlock* target); + + bool IsILBlock() const; + bool IsLowLevelILBlock() const; + bool IsMediumLevelILBlock() const; + Ref GetLowLevelILFunction() const; + Ref GetMediumLevelILFunction() const; }; struct VariableNameAndType @@ -2570,6 +2578,12 @@ namespace BinaryNinja bool IsOptionSet(BNDisassemblyOption option) const; void SetOption(BNDisassemblyOption option, bool state = true); + + bool IsILGraph() const; + bool IsLowLevelILGraph() const; + bool IsMediumLevelILGraph() const; + Ref GetLowLevelILFunction() const; + Ref GetMediumLevelILFunction() const; }; struct LowLevelILLabel: public BNLowLevelILLabel @@ -3312,7 +3326,10 @@ namespace BinaryNinja { Ref view; uint64_t address, length; + size_t instrIndex; Ref function; + Ref lowLevelILFunction; + Ref mediumLevelILFunction; PluginCommandContext(); }; @@ -3345,15 +3362,55 @@ namespace BinaryNinja std::function isValid; }; + struct RegisteredLowLevelILFunctionCommand + { + std::function action; + std::function isValid; + }; + + struct RegisteredLowLevelILInstructionCommand + { + std::function action; + std::function isValid; + }; + + struct RegisteredMediumLevelILFunctionCommand + { + std::function action; + std::function isValid; + }; + + struct RegisteredMediumLevelILInstructionCommand + { + std::function action; + std::function isValid; + }; + static void DefaultPluginCommandActionCallback(void* ctxt, BNBinaryView* view); static void AddressPluginCommandActionCallback(void* ctxt, BNBinaryView* view, uint64_t addr); static void RangePluginCommandActionCallback(void* ctxt, BNBinaryView* view, uint64_t addr, uint64_t len); static void FunctionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, BNFunction* func); + static void LowLevelILFunctionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNLowLevelILFunction* func); + static void LowLevelILInstructionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNLowLevelILFunction* func, size_t instr); + static void MediumLevelILFunctionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNMediumLevelILFunction* func); + static void MediumLevelILInstructionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNMediumLevelILFunction* func, size_t instr); static bool DefaultPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view); static bool AddressPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, uint64_t addr); static bool RangePluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, uint64_t addr, uint64_t len); static bool FunctionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, BNFunction* func); + static bool LowLevelILFunctionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNLowLevelILFunction* func); + static bool LowLevelILInstructionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNLowLevelILFunction* func, size_t instr); + static bool MediumLevelILFunctionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNMediumLevelILFunction* func); + static bool MediumLevelILInstructionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNMediumLevelILFunction* func, size_t instr); public: PluginCommand(const BNPluginCommand& cmd); @@ -3363,25 +3420,45 @@ namespace BinaryNinja PluginCommand& operator=(const PluginCommand& cmd); static void Register(const std::string& name, const std::string& description, - const std::function& action); + const std::function& action); static void Register(const std::string& name, const std::string& description, - const std::function& action, - const std::function& isValid); + const std::function& action, + const std::function& isValid); static void RegisterForAddress(const std::string& name, const std::string& description, - const std::function& action); + const std::function& action); static void RegisterForAddress(const std::string& name, const std::string& description, - const std::function& action, - const std::function& isValid); + const std::function& action, + const std::function& isValid); static void RegisterForRange(const std::string& name, const std::string& description, - const std::function& action); + const std::function& action); static void RegisterForRange(const std::string& name, const std::string& description, - const std::function& action, - const std::function& isValid); + const std::function& action, + const std::function& isValid); static void RegisterForFunction(const std::string& name, const std::string& description, - const std::function& action); + const std::function& action); static void RegisterForFunction(const std::string& name, const std::string& description, - const std::function& action, - const std::function& isValid); + const std::function& action, + const std::function& isValid); + static void RegisterForLowLevelILFunction(const std::string& name, const std::string& description, + const std::function& action); + static void RegisterForLowLevelILFunction(const std::string& name, const std::string& description, + const std::function& action, + const std::function& isValid); + static void RegisterForLowLevelILInstruction(const std::string& name, const std::string& description, + const std::function& action); + static void RegisterForLowLevelILInstruction(const std::string& name, const std::string& description, + const std::function& action, + const std::function& isValid); + static void RegisterForMediumLevelILFunction(const std::string& name, const std::string& description, + const std::function& action); + static void RegisterForMediumLevelILFunction(const std::string& name, const std::string& description, + const std::function& action, + const std::function& isValid); + static void RegisterForMediumLevelILInstruction(const std::string& name, const std::string& description, + const std::function& action); + static void RegisterForMediumLevelILInstruction(const std::string& name, const std::string& description, + const std::function& action, + const std::function& isValid); static std::vector GetList(); static std::vector GetValidList(const PluginCommandContext& ctxt); diff --git a/binaryninjacore.h b/binaryninjacore.h index cb4b9eb9..69c5e61b 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1205,6 +1205,7 @@ extern "C" struct BNDisassemblyTextLine { uint64_t addr; + size_t instrIndex; BNInstructionTextToken* tokens; size_t count; }; @@ -1365,7 +1366,11 @@ extern "C" DefaultPluginCommand, AddressPluginCommand, RangePluginCommand, - FunctionPluginCommand + FunctionPluginCommand, + LowLevelILFunctionPluginCommand, + LowLevelILInstructionPluginCommand, + MediumLevelILFunctionPluginCommand, + MediumLevelILInstructionPluginCommand }; struct BNPluginCommand @@ -1379,11 +1384,19 @@ extern "C" void (*addressCommand)(void* ctxt, BNBinaryView* view, uint64_t addr); void (*rangeCommand)(void* ctxt, BNBinaryView* view, uint64_t addr, uint64_t len); void (*functionCommand)(void* ctxt, BNBinaryView* view, BNFunction* func); + void (*lowLevelILFunctionCommand)(void* ctxt, BNBinaryView* view, BNLowLevelILFunction* func); + void (*lowLevelILInstructionCommand)(void* ctxt, BNBinaryView* view, BNLowLevelILFunction* func, size_t instr); + void (*mediumLevelILFunctionCommand)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func); + void (*mediumLevelILInstructionCommand)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func, size_t instr); bool (*defaultIsValid)(void* ctxt, BNBinaryView* view); bool (*addressIsValid)(void* ctxt, BNBinaryView* view, uint64_t addr); bool (*rangeIsValid)(void* ctxt, BNBinaryView* view, uint64_t addr, uint64_t len); bool (*functionIsValid)(void* ctxt, BNBinaryView* view, BNFunction* func); + bool (*lowLevelILFunctionIsValid)(void* ctxt, BNBinaryView* view, BNLowLevelILFunction* func); + bool (*lowLevelILInstructionIsValid)(void* ctxt, BNBinaryView* view, BNLowLevelILFunction* func, size_t instr); + bool (*mediumLevelILFunctionIsValid)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func); + bool (*mediumLevelILInstructionIsValid)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func, size_t instr); }; struct BNCustomCallingConvention @@ -2347,6 +2360,11 @@ extern "C" BINARYNINJACOREAPI BNBasicBlock** BNGetBasicBlockDominanceFrontier(BNBasicBlock* block, size_t* count); BINARYNINJACOREAPI BNBasicBlock** BNGetBasicBlockIteratedDominanceFrontier(BNBasicBlock** blocks, size_t incomingCount, size_t* outputCount); + BINARYNINJACOREAPI bool BNIsILBasicBlock(BNBasicBlock* block); + BINARYNINJACOREAPI bool BNIsLowLevelILBasicBlock(BNBasicBlock* block); + BINARYNINJACOREAPI bool BNIsMediumLevelILBasicBlock(BNBasicBlock* block); + BINARYNINJACOREAPI BNLowLevelILFunction* BNGetBasicBlockLowLevelILFunction(BNBasicBlock* block); + BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetBasicBlockMediumLevelILFunction(BNBasicBlock* block); BINARYNINJACOREAPI BNDisassemblyTextLine* BNGetBasicBlockDisassemblyText(BNBasicBlock* block, BNDisassemblySettings* settings, size_t* count); @@ -2547,6 +2565,11 @@ extern "C" BINARYNINJACOREAPI void BNSetFunctionGraphCompleteCallback(BNFunctionGraph* graph, void* ctxt, void (*func)(void* ctxt)); BINARYNINJACOREAPI void BNAbortFunctionGraph(BNFunctionGraph* graph); BINARYNINJACOREAPI BNFunctionGraphType BNGetFunctionGraphType(BNFunctionGraph* graph); + BINARYNINJACOREAPI bool BNIsILFunctionGraph(BNFunctionGraph* graph); + BINARYNINJACOREAPI bool BNIsLowLevelILFunctionGraph(BNFunctionGraph* graph); + BINARYNINJACOREAPI bool BNIsMediumLevelILFunctionGraph(BNFunctionGraph* graph); + BINARYNINJACOREAPI BNLowLevelILFunction* BNGetFunctionGraphLowLevelILFunction(BNFunctionGraph* graph); + BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetFunctionGraphMediumLevelILFunction(BNFunctionGraph* graph); BINARYNINJACOREAPI BNFunctionGraphBlock** BNGetFunctionGraphBlocks(BNFunctionGraph* graph, size_t* count); BINARYNINJACOREAPI BNFunctionGraphBlock** BNGetFunctionGraphBlocksInRegion( @@ -3017,29 +3040,45 @@ extern "C" // Plugin commands BINARYNINJACOREAPI void BNRegisterPluginCommand(const char* name, const char* description, - void (*action)(void* ctxt, BNBinaryView* view), - bool (*isValid)(void* ctxt, BNBinaryView* view), void* context); + void (*action)(void* ctxt, BNBinaryView* view), bool (*isValid)(void* ctxt, BNBinaryView* view), void* context); BINARYNINJACOREAPI void BNRegisterPluginCommandForAddress(const char* name, const char* description, - void (*action)(void* ctxt, BNBinaryView* view, uint64_t addr), - bool (*isValid)(void* ctxt, BNBinaryView* view, uint64_t addr), - void* context); + void (*action)(void* ctxt, BNBinaryView* view, uint64_t addr), + bool (*isValid)(void* ctxt, BNBinaryView* view, uint64_t addr), void* context); BINARYNINJACOREAPI void BNRegisterPluginCommandForRange(const char* name, const char* description, - void (*action)(void* ctxt, BNBinaryView* view, uint64_t addr, uint64_t len), - bool (*isValid)(void* ctxt, BNBinaryView* view, uint64_t addr, uint64_t len), - void* context); + void (*action)(void* ctxt, BNBinaryView* view, uint64_t addr, uint64_t len), + bool (*isValid)(void* ctxt, BNBinaryView* view, uint64_t addr, uint64_t len), void* context); BINARYNINJACOREAPI void BNRegisterPluginCommandForFunction(const char* name, const char* description, - void (*action)(void* ctxt, BNBinaryView* view, BNFunction* func), - bool (*isValid)(void* ctxt, BNBinaryView* view, BNFunction* func), - void* context); + void (*action)(void* ctxt, BNBinaryView* view, BNFunction* func), + bool (*isValid)(void* ctxt, BNBinaryView* view, BNFunction* func), void* context); + BINARYNINJACOREAPI void BNRegisterPluginCommandForLowLevelILFunction(const char* name, const char* description, + void (*action)(void* ctxt, BNBinaryView* view, BNLowLevelILFunction* func), + bool (*isValid)(void* ctxt, BNBinaryView* view, BNLowLevelILFunction* func), void* context); + BINARYNINJACOREAPI void BNRegisterPluginCommandForLowLevelILInstruction(const char* name, const char* description, + void (*action)(void* ctxt, BNBinaryView* view, BNLowLevelILFunction* func, size_t instr), + bool (*isValid)(void* ctxt, BNBinaryView* view, BNLowLevelILFunction* func, size_t instr), void* context); + BINARYNINJACOREAPI void BNRegisterPluginCommandForMediumLevelILFunction(const char* name, const char* description, + void (*action)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func), + bool (*isValid)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func), void* context); + BINARYNINJACOREAPI void BNRegisterPluginCommandForMediumLevelILInstruction(const char* name, const char* description, + void (*action)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func, size_t instr), + bool (*isValid)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func, size_t instr), void* context); BINARYNINJACOREAPI BNPluginCommand* BNGetAllPluginCommands(size_t* count); BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommands(BNBinaryView* view, size_t* count); BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommandsForAddress(BNBinaryView* view, uint64_t addr, - size_t* count); + size_t* count); BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommandsForRange(BNBinaryView* view, uint64_t addr, - uint64_t len, size_t* count); + uint64_t len, size_t* count); BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommandsForFunction(BNBinaryView* view, BNFunction* func, - size_t* count); + size_t* count); + BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommandsForLowLevelILFunction(BNBinaryView* view, + BNLowLevelILFunction* func, size_t* count); + BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommandsForLowLevelILInstruction(BNBinaryView* view, + BNLowLevelILFunction* func, size_t instr, size_t* count); + BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommandsForMediumLevelILFunction(BNBinaryView* view, + BNMediumLevelILFunction* func, size_t* count); + BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommandsForMediumLevelILInstruction(BNBinaryView* view, + BNMediumLevelILFunction* func, size_t instr, size_t* count); BINARYNINJACOREAPI void BNFreePluginCommandList(BNPluginCommand* commands); // Calling conventions diff --git a/binaryview.cpp b/binaryview.cpp index 8dcae40f..0a9a7118 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1459,6 +1459,7 @@ vector BinaryView::GetPreviousLinearDisassemblyLines(Line line.block = lines[i].block ? new BasicBlock(BNNewBasicBlockReference(lines[i].block)) : nullptr; line.lineOffset = lines[i].lineOffset; line.contents.addr = lines[i].contents.addr; + line.contents.instrIndex = lines[i].contents.instrIndex; line.contents.tokens.reserve(lines[i].contents.count); for (size_t j = 0; j < lines[i].contents.count; j++) { @@ -1507,6 +1508,7 @@ vector BinaryView::GetNextLinearDisassemblyLines(LinearDi line.block = lines[i].block ? new BasicBlock(BNNewBasicBlockReference(lines[i].block)) : nullptr; line.lineOffset = lines[i].lineOffset; line.contents.addr = lines[i].contents.addr; + line.contents.instrIndex = lines[i].contents.instrIndex; line.contents.tokens.reserve(lines[i].contents.count); for (size_t j = 0; j < lines[i].contents.count; j++) { diff --git a/function.cpp b/function.cpp index 1e91f8f3..835ab144 100644 --- a/function.cpp +++ b/function.cpp @@ -1337,6 +1337,7 @@ vector Function::GetTypeTokens(DisassemblySettings* setting { DisassemblyTextLine line; line.addr = lines[i].addr; + line.instrIndex = lines[i].instrIndex; line.tokens.reserve(lines[i].count); for (size_t j = 0; j < lines[i].count; j++) { diff --git a/functiongraph.cpp b/functiongraph.cpp index a743254e..9948d70e 100644 --- a/functiongraph.cpp +++ b/functiongraph.cpp @@ -186,3 +186,39 @@ void FunctionGraph::SetOption(BNDisassemblyOption option, bool state) { BNSetFunctionGraphOption(m_graph, option, state); } + + +bool FunctionGraph::IsILGraph() const +{ + return BNIsILFunctionGraph(m_graph); +} + + +bool FunctionGraph::IsLowLevelILGraph() const +{ + return BNIsLowLevelILFunctionGraph(m_graph); +} + + +bool FunctionGraph::IsMediumLevelILGraph() const +{ + return BNIsMediumLevelILFunctionGraph(m_graph); +} + + +Ref FunctionGraph::GetLowLevelILFunction() const +{ + BNLowLevelILFunction* func = BNGetFunctionGraphLowLevelILFunction(m_graph); + if (!func) + return nullptr; + return new LowLevelILFunction(func); +} + + +Ref FunctionGraph::GetMediumLevelILFunction() const +{ + BNMediumLevelILFunction* func = BNGetFunctionGraphMediumLevelILFunction(m_graph); + if (!func) + return nullptr; + return new MediumLevelILFunction(func); +} diff --git a/functiongraphblock.cpp b/functiongraphblock.cpp index 06a35eee..469fb175 100644 --- a/functiongraphblock.cpp +++ b/functiongraphblock.cpp @@ -94,6 +94,7 @@ const vector& FunctionGraphBlock::GetLines() { DisassemblyTextLine line; line.addr = lines[i].addr; + line.instrIndex = lines[i].instrIndex; line.tokens.reserve(lines[i].count); for (size_t j = 0; j < lines[i].count; j++) { diff --git a/plugin.cpp b/plugin.cpp index 972ce28b..22befd65 100644 --- a/plugin.cpp +++ b/plugin.cpp @@ -19,6 +19,8 @@ // IN THE SOFTWARE. #include "binaryninjaapi.h" +#include "lowlevelilinstruction.h" +#include "mediumlevelilinstruction.h" using namespace BinaryNinja; using namespace std; @@ -27,6 +29,7 @@ using namespace std; PluginCommandContext::PluginCommandContext() { address = length = 0; + instrIndex = BN_INVALID_EXPR; } @@ -97,6 +100,48 @@ void PluginCommand::FunctionPluginCommandActionCallback(void* ctxt, BNBinaryView } +void PluginCommand::LowLevelILFunctionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNLowLevelILFunction* func) +{ + RegisteredLowLevelILFunctionCommand* cmd = (RegisteredLowLevelILFunctionCommand*)ctxt; + Ref viewObject = new BinaryView(BNNewViewReference(view)); + Ref funcObject = new LowLevelILFunction(BNNewLowLevelILFunctionReference(func)); + cmd->action(viewObject, funcObject); +} + + +void PluginCommand::LowLevelILInstructionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNLowLevelILFunction* func, size_t instr) +{ + RegisteredLowLevelILInstructionCommand* cmd = (RegisteredLowLevelILInstructionCommand*)ctxt; + Ref viewObject = new BinaryView(BNNewViewReference(view)); + Ref funcObject = new LowLevelILFunction(BNNewLowLevelILFunctionReference(func)); + LowLevelILInstruction instrObject = funcObject->GetInstruction(instr); + cmd->action(viewObject, instrObject); +} + + +void PluginCommand::MediumLevelILFunctionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNMediumLevelILFunction* func) +{ + RegisteredMediumLevelILFunctionCommand* cmd = (RegisteredMediumLevelILFunctionCommand*)ctxt; + Ref viewObject = new BinaryView(BNNewViewReference(view)); + Ref funcObject = new MediumLevelILFunction(BNNewMediumLevelILFunctionReference(func)); + cmd->action(viewObject, funcObject); +} + + +void PluginCommand::MediumLevelILInstructionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNMediumLevelILFunction* func, size_t instr) +{ + RegisteredMediumLevelILInstructionCommand* cmd = (RegisteredMediumLevelILInstructionCommand*)ctxt; + Ref viewObject = new BinaryView(BNNewViewReference(view)); + Ref funcObject = new MediumLevelILFunction(BNNewMediumLevelILFunctionReference(func)); + MediumLevelILInstruction instrObject = funcObject->GetInstruction(instr); + cmd->action(viewObject, instrObject); +} + + bool PluginCommand::DefaultPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view) { RegisteredDefaultCommand* cmd = (RegisteredDefaultCommand*)ctxt; @@ -130,6 +175,48 @@ bool PluginCommand::FunctionPluginCommandIsValidCallback(void* ctxt, BNBinaryVie } +bool PluginCommand::LowLevelILFunctionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNLowLevelILFunction* func) +{ + RegisteredLowLevelILFunctionCommand* cmd = (RegisteredLowLevelILFunctionCommand*)ctxt; + Ref viewObject = new BinaryView(BNNewViewReference(view)); + Ref funcObject = new LowLevelILFunction(BNNewLowLevelILFunctionReference(func)); + return cmd->isValid(viewObject, funcObject); +} + + +bool PluginCommand::LowLevelILInstructionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNLowLevelILFunction* func, size_t instr) +{ + RegisteredLowLevelILInstructionCommand* cmd = (RegisteredLowLevelILInstructionCommand*)ctxt; + Ref viewObject = new BinaryView(BNNewViewReference(view)); + Ref funcObject = new LowLevelILFunction(BNNewLowLevelILFunctionReference(func)); + LowLevelILInstruction instrObject = funcObject->GetInstruction(instr); + return cmd->isValid(viewObject, instrObject); +} + + +bool PluginCommand::MediumLevelILFunctionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNMediumLevelILFunction* func) +{ + RegisteredMediumLevelILFunctionCommand* cmd = (RegisteredMediumLevelILFunctionCommand*)ctxt; + Ref viewObject = new BinaryView(BNNewViewReference(view)); + Ref funcObject = new MediumLevelILFunction(BNNewMediumLevelILFunctionReference(func)); + return cmd->isValid(viewObject, funcObject); +} + + +bool PluginCommand::MediumLevelILInstructionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNMediumLevelILFunction* func, size_t instr) +{ + RegisteredMediumLevelILInstructionCommand* cmd = (RegisteredMediumLevelILInstructionCommand*)ctxt; + Ref viewObject = new BinaryView(BNNewViewReference(view)); + Ref funcObject = new MediumLevelILFunction(BNNewMediumLevelILFunctionReference(func)); + MediumLevelILInstruction instrObject = funcObject->GetInstruction(instr); + return cmd->isValid(viewObject, instrObject); +} + + void PluginCommand::Register(const string& name, const string& description, const function& action) { @@ -206,6 +293,89 @@ void PluginCommand::RegisterForFunction(const string& name, const string& descri } +void PluginCommand::RegisterForLowLevelILFunction(const string& name, const string& description, + const function& action) +{ + RegisterForLowLevelILFunction(name, description, action, [](BinaryView*, LowLevelILFunction*) { return true; }); +} + + +void PluginCommand::RegisterForLowLevelILFunction(const string& name, const string& description, + const function& action, + const function& isValid) +{ + RegisteredLowLevelILFunctionCommand* cmd = new RegisteredLowLevelILFunctionCommand; + cmd->action = action; + cmd->isValid = isValid; + BNRegisterPluginCommandForLowLevelILFunction(name.c_str(), description.c_str(), + LowLevelILFunctionPluginCommandActionCallback, + LowLevelILFunctionPluginCommandIsValidCallback, cmd); +} + + +void PluginCommand::RegisterForLowLevelILInstruction(const string& name, const string& description, + const function& action) +{ + RegisterForLowLevelILInstruction(name, description, action, + [](BinaryView*, const LowLevelILInstruction&) { return true; }); +} + + +void PluginCommand::RegisterForLowLevelILInstruction(const string& name, const string& description, + const function& action, + const function& isValid) +{ + RegisteredLowLevelILInstructionCommand* cmd = new RegisteredLowLevelILInstructionCommand; + cmd->action = action; + cmd->isValid = isValid; + BNRegisterPluginCommandForLowLevelILInstruction(name.c_str(), description.c_str(), + LowLevelILInstructionPluginCommandActionCallback, + LowLevelILInstructionPluginCommandIsValidCallback, cmd); +} + + +void PluginCommand::RegisterForMediumLevelILFunction(const string& name, const string& description, + const function& action) +{ + RegisterForMediumLevelILFunction(name, description, action, + [](BinaryView*, MediumLevelILFunction*) { return true; }); +} + + +void PluginCommand::RegisterForMediumLevelILFunction(const string& name, const string& description, + const function& action, + const function& isValid) +{ + RegisteredMediumLevelILFunctionCommand* cmd = new RegisteredMediumLevelILFunctionCommand; + cmd->action = action; + cmd->isValid = isValid; + BNRegisterPluginCommandForMediumLevelILFunction(name.c_str(), description.c_str(), + MediumLevelILFunctionPluginCommandActionCallback, + MediumLevelILFunctionPluginCommandIsValidCallback, cmd); +} + + +void PluginCommand::RegisterForMediumLevelILInstruction(const string& name, const string& description, + const function& action) +{ + RegisterForMediumLevelILInstruction(name, description, action, + [](BinaryView*, const MediumLevelILInstruction&) { return true; }); +} + + +void PluginCommand::RegisterForMediumLevelILInstruction(const string& name, const string& description, + const function& action, + const function& isValid) +{ + RegisteredMediumLevelILInstructionCommand* cmd = new RegisteredMediumLevelILInstructionCommand; + cmd->action = action; + cmd->isValid = isValid; + BNRegisterPluginCommandForMediumLevelILInstruction(name.c_str(), description.c_str(), + MediumLevelILInstructionPluginCommandActionCallback, + MediumLevelILInstructionPluginCommandIsValidCallback, cmd); +} + + vector PluginCommand::GetList() { vector result; @@ -259,6 +429,38 @@ bool PluginCommand::IsValid(const PluginCommandContext& ctxt) const if (!m_command.functionIsValid) return true; return m_command.functionIsValid(m_command.context, ctxt.view->GetObject(), ctxt.function->GetObject()); + case LowLevelILFunctionPluginCommand: + if (!ctxt.lowLevelILFunction) + return false; + if (!m_command.lowLevelILFunctionIsValid) + return true; + return m_command.lowLevelILFunctionIsValid(m_command.context, ctxt.view->GetObject(), + ctxt.lowLevelILFunction->GetObject()); + case LowLevelILInstructionPluginCommand: + if (!ctxt.lowLevelILFunction) + return false; + if (ctxt.instrIndex == BN_INVALID_EXPR) + return false; + if (!m_command.lowLevelILInstructionIsValid) + return true; + return m_command.lowLevelILInstructionIsValid(m_command.context, ctxt.view->GetObject(), + ctxt.lowLevelILFunction->GetObject(), ctxt.instrIndex); + case MediumLevelILFunctionPluginCommand: + if (!ctxt.mediumLevelILFunction) + return false; + if (!m_command.mediumLevelILFunctionIsValid) + return true; + return m_command.mediumLevelILFunctionIsValid(m_command.context, ctxt.view->GetObject(), + ctxt.mediumLevelILFunction->GetObject()); + case MediumLevelILInstructionPluginCommand: + if (!ctxt.mediumLevelILFunction) + return false; + if (ctxt.instrIndex == BN_INVALID_EXPR) + return false; + if (!m_command.mediumLevelILInstructionIsValid) + return true; + return m_command.mediumLevelILInstructionIsValid(m_command.context, ctxt.view->GetObject(), + ctxt.mediumLevelILFunction->GetObject(), ctxt.instrIndex); default: return false; } @@ -284,6 +486,22 @@ void PluginCommand::Execute(const PluginCommandContext& ctxt) const case FunctionPluginCommand: m_command.functionCommand(m_command.context, ctxt.view->GetObject(), ctxt.function->GetObject()); break; + case LowLevelILFunctionPluginCommand: + m_command.lowLevelILFunctionCommand(m_command.context, ctxt.view->GetObject(), + ctxt.lowLevelILFunction->GetObject()); + break; + case LowLevelILInstructionPluginCommand: + m_command.lowLevelILInstructionCommand(m_command.context, ctxt.view->GetObject(), + ctxt.lowLevelILFunction->GetObject(), ctxt.instrIndex); + break; + case MediumLevelILFunctionPluginCommand: + m_command.mediumLevelILFunctionCommand(m_command.context, ctxt.view->GetObject(), + ctxt.mediumLevelILFunction->GetObject()); + break; + case MediumLevelILInstructionPluginCommand: + m_command.mediumLevelILInstructionCommand(m_command.context, ctxt.view->GetObject(), + ctxt.mediumLevelILFunction->GetObject(), ctxt.instrIndex); + break; default: break; } diff --git a/python/basicblock.py b/python/basicblock.py index 1d932c5e..4dc783c3 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -256,6 +256,21 @@ class BasicBlock(object): def highlight(self, value): self.set_user_highlight(value) + @property + def is_il(self): + """Whether the basic block contains IL""" + return core.BNIsILBasicBlock(self.handle) + + @property + def is_low_level_il(self): + """Whether the basic block contains Low Level IL""" + return core.BNIsLowLevelILBasicBlock(self.handle) + + @property + def is_medium_level_il(self): + """Whether the basic block contains Medium Level IL""" + return core.BNIsMediumLevelILBasicBlock(self.handle) + @classmethod def get_iterated_dominance_frontier(self, blocks): if len(blocks) == 0: @@ -322,6 +337,10 @@ class BasicBlock(object): result = [] for i in xrange(0, count.value): addr = lines[i].addr + if (lines[i].instrIndex != 0xffffffffffffffff) and hasattr(self, 'il_function'): + il_instr = self.il_function[lines[i].instrIndex] + else: + il_instr = None tokens = [] for j in xrange(0, lines[i].count): token_type = InstructionTextTokenType(lines[i].tokens[j].type) @@ -333,7 +352,7 @@ class BasicBlock(object): confidence = lines[i].tokens[j].confidence address = lines[i].tokens[j].address tokens.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) - result.append(function.DisassemblyTextLine(addr, tokens)) + result.append(function.DisassemblyTextLine(addr, tokens, il_instr)) core.BNFreeDisassemblyTextLines(lines, count.value) return result diff --git a/python/function.py b/python/function.py index 1cc4dcac..6db44e6d 100644 --- a/python/function.py +++ b/python/function.py @@ -1598,9 +1598,10 @@ class AdvancedFunctionAnalysisDataRequestor(object): class DisassemblyTextLine(object): - def __init__(self, addr, tokens): + def __init__(self, addr, tokens, il_instr = None): self.address = addr self.tokens = tokens + self.il_instruction = il_instr def __str__(self): result = "" @@ -1625,8 +1626,9 @@ class FunctionGraphEdge(object): class FunctionGraphBlock(object): - def __init__(self, handle): + def __init__(self, handle, graph): self.handle = handle + self.graph = graph def __del__(self): core.BNFreeFunctionGraphBlock(self.handle) @@ -1645,13 +1647,22 @@ class FunctionGraphBlock(object): def basic_block(self): """Basic block associated with this part of the function graph (read-only)""" block = core.BNGetFunctionGraphBasicBlock(self.handle) - func = core.BNGetBasicBlockFunction(block) - if func is None: + func_handle = core.BNGetBasicBlockFunction(block) + if func_handle is None: core.BNFreeBasicBlock(block) - block = None + return None + + view = binaryview.BinaryView(handle = core.BNGetFunctionData(func_handle)) + func = Function(view, func_handle) + + if core.BNIsLowLevelILBasicBlock(block): + block = lowlevelil.LowLevelILBasicBlock(view, block, + lowlevelil.LowLevelILFunction(func.arch, core.BNGetBasicBlockLowLevelILFunction(block), func)) + elif core.BNIsMediumLevelILBasicBlock(block): + block = mediumlevelil.MediumLevelILBasicBlock(view, block, + mediumlevelil.MediumLevelILFunction(func.arch, core.BNGetBasicBlockMediumLevelILFunction(block), func)) else: - block = basicblock.BasicBlock(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), block) - core.BNFreeFunction(func) + block = basicblock.BasicBlock(view, block) return block @property @@ -1697,9 +1708,14 @@ class FunctionGraphBlock(object): """Function graph block list of lines (read-only)""" count = ctypes.c_ulonglong() lines = core.BNGetFunctionGraphBlockLines(self.handle, count) + block = self.basic_block result = [] for i in xrange(0, count.value): addr = lines[i].addr + if (lines[i].instrIndex != 0xffffffffffffffff) and hasattr(block, 'il_function'): + il_instr = block.il_function[lines[i].instrIndex] + else: + il_instr = None tokens = [] for j in xrange(0, lines[i].count): token_type = InstructionTextTokenType(lines[i].tokens[j].type) @@ -1711,7 +1727,7 @@ class FunctionGraphBlock(object): confidence = lines[i].tokens[j].confidence address = lines[i].tokens[j].address tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) - result.append(DisassemblyTextLine(addr, tokens)) + result.append(DisassemblyTextLine(addr, tokens, il_instr)) core.BNFreeDisassemblyTextLines(lines, count.value) return result @@ -1756,9 +1772,14 @@ class FunctionGraphBlock(object): def __iter__(self): count = ctypes.c_ulonglong() lines = core.BNGetFunctionGraphBlockLines(self.handle, count) + block = self.basic_block try: for i in xrange(0, count.value): addr = lines[i].addr + if (lines[i].instrIndex != 0xffffffffffffffff) and hasattr(block, 'il_function'): + il_instr = block.il_function[lines[i].instrIndex] + else: + il_instr = None tokens = [] for j in xrange(0, lines[i].count): token_type = InstructionTextTokenType(lines[i].tokens[j].type) @@ -1770,7 +1791,7 @@ class FunctionGraphBlock(object): confidence = lines[i].tokens[j].confidence address = lines[i].tokens[j].address tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) - yield DisassemblyTextLine(addr, tokens) + yield DisassemblyTextLine(addr, tokens, il_instr) finally: core.BNFreeDisassemblyTextLines(lines, count.value) @@ -1858,7 +1879,7 @@ class FunctionGraph(object): blocks = core.BNGetFunctionGraphBlocks(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]))) + result.append(FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]), self)) core.BNFreeFunctionGraphBlockList(blocks, count.value) return result @@ -1897,6 +1918,32 @@ class FunctionGraph(object): def settings(self): return DisassemblySettings(core.BNGetFunctionGraphSettings(self.handle)) + @property + def is_il(self): + return core.BNIsILFunctionGraph(self.handle) + + @property + def is_low_level_il(self): + return core.BNIsLowLevelILFunctionGraph(self.handle) + + @property + def is_medium_level_il(self): + return core.BNIsMediumLevelILFunctionGraph(self.handle) + + @property + def il_function(self): + if self.is_low_level_il: + il_func = core.BNGetFunctionGraphLowLevelILFunction(self.handle) + if not il_func: + return None + return lowlevelil.LowLevelILFunction(self.function.arch, il_func, self.function) + if self.is_medium_level_il: + il_func = core.BNGetFunctionGraphMediumLevelILFunction(self.handle) + if not il_func: + return None + return mediumlevelil.MediumLevelILFunction(self.function.arch, il_func, self.function) + return None + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) @@ -1911,7 +1958,7 @@ class FunctionGraph(object): blocks = core.BNGetFunctionGraphBlocks(self.handle, count) try: for i in xrange(0, count.value): - yield FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i])) + yield FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]), self) finally: core.BNFreeFunctionGraphBlockList(blocks, count.value) @@ -1954,7 +2001,7 @@ class FunctionGraph(object): blocks = core.BNGetFunctionGraphBlocksInRegion(self.handle, left, top, right, bottom, count) result = [] for i in xrange(0, count.value): - result.append(FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]))) + result.append(FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]), self)) core.BNFreeFunctionGraphBlockList(blocks, count.value) return result diff --git a/python/plugin.py b/python/plugin.py index e0054d86..c6cd9fc0 100644 --- a/python/plugin.py +++ b/python/plugin.py @@ -30,6 +30,8 @@ import filemetadata import binaryview import function import log +import lowlevelil +import mediumlevelil class PluginCommandContext(object): @@ -38,6 +40,7 @@ class PluginCommandContext(object): self.address = 0 self.length = 0 self.function = None + self.instruction = None class _PluginCommandMetaClass(type): @@ -117,6 +120,50 @@ class PluginCommand(object): except: log.log_error(traceback.format_exc()) + @classmethod + def _low_level_il_function_action(cls, view, func, action): + try: + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetLowLevelILOwnerFunction(func)) + func_obj = lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) + action(view_obj, func_obj) + except: + log.log_error(traceback.format_exc()) + + @classmethod + def _low_level_il_instruction_action(cls, view, func, instr, action): + try: + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetLowLevelILOwnerFunction(func)) + func_obj = lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) + action(view_obj, func_obj[instr]) + except: + log.log_error(traceback.format_exc()) + + @classmethod + def _medium_level_il_function_action(cls, view, func, action): + try: + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetMediumLevelILOwnerFunction(func)) + func_obj = mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) + action(view_obj, func_obj) + except: + log.log_error(traceback.format_exc()) + + @classmethod + def _medium_level_il_instruction_action(cls, view, func, instr, action): + try: + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetMediumLevelILOwnerFunction(func)) + func_obj = mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) + action(view_obj, func_obj[instr]) + except: + log.log_error(traceback.format_exc()) + @classmethod def _default_is_valid(cls, view, is_valid): try: @@ -166,6 +213,62 @@ class PluginCommand(object): log.log_error(traceback.format_exc()) return False + @classmethod + def _low_level_il_function_is_valid(cls, view, func, is_valid): + try: + if is_valid is None: + return True + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetLowLevelILOwnerFunction(func)) + func_obj = lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) + return is_valid(view_obj, func_obj) + except: + log.log_error(traceback.format_exc()) + return False + + @classmethod + def _low_level_il_instruction_is_valid(cls, view, func, instr, is_valid): + try: + if is_valid is None: + return True + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetLowLevelILOwnerFunction(func)) + func_obj = lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) + return is_valid(view_obj, func_obj[instr]) + except: + log.log_error(traceback.format_exc()) + return False + + @classmethod + def _medium_level_il_function_is_valid(cls, view, func, is_valid): + try: + if is_valid is None: + return True + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetMediumLevelILOwnerFunction(func)) + func_obj = mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) + return is_valid(view_obj, func_obj) + except: + log.log_error(traceback.format_exc()) + return False + + @classmethod + def _medium_level_il_instruction_is_valid(cls, view, func, instr, is_valid): + try: + if is_valid is None: + return True + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetMediumLevelILOwnerFunction(func)) + func_obj = mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) + return is_valid(view_obj, func_obj[instr]) + except: + log.log_error(traceback.format_exc()) + return False + @classmethod def register(cls, name, description, action, is_valid = None): """ @@ -242,6 +345,82 @@ class PluginCommand(object): cls._registered_commands.append((action_obj, is_valid_obj)) core.BNRegisterPluginCommandForFunction(name, description, action_obj, is_valid_obj, None) + @classmethod + def register_for_low_level_il_function(cls, name, description, action, is_valid = None): + """ + ``register_for_low_level_il_function`` Register a plugin to be called with a low level IL function argument + + :param str name: name of the plugin + :param str description: description of the plugin + :param action: function to call with the ``BinaryView`` and a ``LowLevelILFunction`` as arguments + :param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view + :rtype: None + + .. warning:: Calling ``register_for_low_level_il_function`` with the same function name will replace the existing function but will leak the memory of the original plugin. + """ + startup._init_plugins() + action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction))(lambda ctxt, view, func: cls._low_level_il_function_action(view, func, action)) + is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction))(lambda ctxt, view, func: cls._low_level_il_function_is_valid(view, func, is_valid)) + cls._registered_commands.append((action_obj, is_valid_obj)) + core.BNRegisterPluginCommandForLowLevelILFunction(name, description, action_obj, is_valid_obj, None) + + @classmethod + def register_for_low_level_il_instruction(cls, name, description, action, is_valid = None): + """ + ``register_for_low_level_il_instruction`` Register a plugin to be called with a low level IL instruction argument + + :param str name: name of the plugin + :param str description: description of the plugin + :param action: function to call with the ``BinaryView`` and a ``LowLevelILInstruction`` as arguments + :param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view + :rtype: None + + .. warning:: Calling ``register_for_low_level_il_instruction`` with the same function name will replace the existing function but will leak the memory of the original plugin. + """ + startup._init_plugins() + action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._low_level_il_instruction_action(view, func, instr, action)) + is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._low_level_il_instruction_is_valid(view, func, instr, is_valid)) + cls._registered_commands.append((action_obj, is_valid_obj)) + core.BNRegisterPluginCommandForLowLevelILInstruction(name, description, action_obj, is_valid_obj, None) + + @classmethod + def register_for_medium_level_il_function(cls, name, description, action, is_valid = None): + """ + ``register_for_medium_level_il_function`` Register a plugin to be called with a medium level IL function argument + + :param str name: name of the plugin + :param str description: description of the plugin + :param action: function to call with the ``BinaryView`` and a ``MediumLevelILFunction`` as arguments + :param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view + :rtype: None + + .. warning:: Calling ``register_for_medium_level_il_function`` with the same function name will replace the existing function but will leak the memory of the original plugin. + """ + startup._init_plugins() + action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction))(lambda ctxt, view, func: cls._medium_level_il_function_action(view, func, action)) + is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction))(lambda ctxt, view, func: cls._medium_level_il_function_is_valid(view, func, is_valid)) + cls._registered_commands.append((action_obj, is_valid_obj)) + core.BNRegisterPluginCommandForMediumLevelILFunction(name, description, action_obj, is_valid_obj, None) + + @classmethod + def register_for_medium_level_il_instruction(cls, name, description, action, is_valid = None): + """ + ``register_for_medium_level_il_instruction`` Register a plugin to be called with a medium level IL instruction argument + + :param str name: name of the plugin + :param str description: description of the plugin + :param action: function to call with the ``BinaryView`` and a ``MediumLevelILInstruction`` as arguments + :param is_valid: optional argument of a function passed a ``BinaryView`` to determine whether the plugin should be enabled for that view + :rtype: None + + .. warning:: Calling ``register_for_medium_level_il_instruction`` with the same function name will replace the existing function but will leak the memory of the original plugin. + """ + startup._init_plugins() + action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._medium_level_il_instruction_action(view, func, instr, action)) + is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._medium_level_il_instruction_is_valid(view, func, instr, is_valid)) + cls._registered_commands.append((action_obj, is_valid_obj)) + core.BNRegisterPluginCommandForMediumLevelILInstruction(name, description, action_obj, is_valid_obj, None) + @classmethod def get_valid_list(cls, context): """Dict of registered plugins""" @@ -275,6 +454,36 @@ class PluginCommand(object): if not self.command.functionIsValid: return True return self.command.functionIsValid(self.command.context, context.view.handle, context.function.handle) + elif self.command.type == PluginCommandType.LowLevelILFunctionPluginCommand: + if context.function is None: + return False + if not self.command.lowLevelILFunctionIsValid: + return True + return self.command.lowLevelILFunctionIsValid(self.command.context, context.view.handle, context.function.handle) + elif self.command.type == PluginCommandType.LowLevelILInstructionPluginCommand: + if context.instruction is None: + return False + if not isinstance(context.instruction, lowlevelil.LowLevelILInstruction): + return False + if not self.command.lowLevelILInstructionIsValid: + return True + return self.command.lowLevelILInstructionIsValid(self.command.context, context.view.handle, + context.instruction.function.handle, context.instruction.instr_index) + elif self.command.type == PluginCommandType.MediumLevelILFunctionPluginCommand: + if context.function is None: + return False + if not self.command.mediumLevelILFunctionIsValid: + return True + return self.command.mediumLevelILFunctionIsValid(self.command.context, context.view.handle, context.function.handle) + elif self.command.type == PluginCommandType.MediumLevelILInstructionPluginCommand: + if context.instruction is None: + return False + if not isinstance(context.instruction, mediumlevelil.MediumLevelILInstruction): + return False + if not self.command.mediumLevelILInstructionIsValid: + return True + return self.command.mediumLevelILInstructionIsValid(self.command.context, context.view.handle, + context.instruction.function.handle, context.instruction.instr_index) return False def execute(self, context): @@ -288,6 +497,16 @@ class PluginCommand(object): self.command.rangeCommand(self.command.context, context.view.handle, context.address, context.length) elif self.command.type == PluginCommandType.FunctionPluginCommand: self.command.functionCommand(self.command.context, context.view.handle, context.function.handle) + elif self.command.type == PluginCommandType.LowLevelILFunctionPluginCommand: + self.command.lowLevelILFunctionCommand(self.command.context, context.view.handle, context.function.handle) + elif self.command.type == PluginCommandType.LowLevelILInstructionPluginCommand: + self.command.lowLevelILInstructionCommand(self.command.context, context.view.handle, + context.instruction.function.handle, context.instruction.instr_index) + elif self.command.type == PluginCommandType.MediumLevelILFunctionPluginCommand: + self.command.mediumLevelILFunctionCommand(self.command.context, context.view.handle, context.function.handle) + elif self.command.type == PluginCommandType.MediumLevelILInstructionPluginCommand: + self.command.mediumLevelILInstructionCommand(self.command.context, context.view.handle, + context.instruction.function.handle, context.instruction.instr_index) def __repr__(self): return "" % self.name -- cgit v1.3.1