From 990cface5a0b9b814f423e45449a7d5f3cb6c19d Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 1 Dec 2016 17:22:22 -0500 Subject: Adding APIs to manipulate structures --- python/__init__.py | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'python/__init__.py') diff --git a/python/__init__.py b/python/__init__.py index 1751fefa..cc138009 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -576,6 +576,12 @@ class BinaryDataNotification: def string_removed(self, view, string_type, offset, length): pass + def type_defined(self, view, name, type): + pass + + def type_undefined(self, view, name, type): + pass + class UndoAction: name = None action_type = None @@ -671,6 +677,8 @@ class BinaryDataNotificationCallbacks(object): self._cb.dataVariableUpdated = self._cb.dataVariableUpdated.__class__(self._data_var_updated) self._cb.stringFound = self._cb.stringFound.__class__(self._string_found) self._cb.stringRemoved = self._cb.stringRemoved.__class__(self._string_removed) + self._cb.typeDefined = self._cb.typeDefined.__class__(self._type_defined) + self._cb.typeUndefined = self._cb.typeUndefined.__class__(self._type_undefined) def _register(self): core.BNRegisterDataNotification(self.view.handle, self._cb) @@ -753,6 +761,18 @@ class BinaryDataNotificationCallbacks(object): except: log_error(traceback.format_exc()) + def _type_defined(self, ctxt, name, type_obj): + try: + self.notify.type_defined(self.view, name, Type(core.BNNewTypeReference(type_obj))) + except: + log_error(traceback.format_exc()) + + def _type_undefined(self, ctxt, name, type_obj): + try: + self.notify.type_undefined(self.view, name, Type(core.BNNewTypeReference(type_obj))) + except: + log_error(traceback.format_exc()) + class _BinaryViewTypeMetaclass(type): @property def list(self): @@ -4447,14 +4467,22 @@ class Structure(object): @property def width(self): - """Structure width (read-only)""" + """Structure width""" return core.BNGetStructureWidth(self.handle) + @width.setter + def width(self, new_width): + core.BNSetStructureWidth(self.handle, new_width) + @property def alignment(self): - """Structure alignment (read-only)""" + """Structure alignment""" return core.BNGetStructureAlignment(self.handle) + @alignment.setter + def alignment(self, align): + core.BNSetStructureAlignment(self.handle, align) + @property def packed(self): return core.BNIsStructurePacked(self.handle) -- cgit v1.3.1 From 09a68bdd84d4789626f5c8b8631f61e7a41ca03d Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Wed, 11 Jan 2017 15:42:08 -0500 Subject: Use named type references for registered types, use qualified names for types --- architecture.cpp | 57 +++++++--- binaryninjaapi.h | 62 ++++++----- binaryninjacore.h | 71 ++++++++----- binaryview.cpp | 134 +++++++++++++++++++----- python/__init__.py | 290 ++++++++++++++++++++++++++++++++++++++------------- python/generator.cpp | 46 ++++---- type.cpp | 111 +++++++++----------- 7 files changed, 533 insertions(+), 238 deletions(-) (limited to 'python/__init__.py') diff --git a/architecture.cpp b/architecture.cpp index e84b7f78..d0d87df4 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -746,9 +746,8 @@ void Architecture::SetBinaryViewTypeConstant(const string& type, const string& n bool Architecture::ParseTypesFromSource(const string& source, const string& fileName, - map>& types, map>& variables, - map>& functions, string& errors, - const vector& includeDirs) + map, Ref>& types, map, Ref>& variables, + map, Ref>& functions, string& errors, const vector& includeDirs) { BNTypeParserResult result; char* errorStr; @@ -762,26 +761,41 @@ bool Architecture::ParseTypesFromSource(const string& source, const string& file functions.clear(); bool ok = BNParseTypesFromSource(m_object, source.c_str(), fileName.c_str(), &result, - &errorStr, includeDirList, includeDirs.size()); + &errorStr, includeDirList, includeDirs.size()); errors = errorStr; BNFreeString(errorStr); if (!ok) return false; for (size_t i = 0; i < result.typeCount; i++) - types[result.types[i].name] = new Type(BNNewTypeReference(result.types[i].type)); + { + vector name; + for (size_t j = 0; j < result.types[i].nameCount; j++) + name.push_back(result.types[i].name[j]); + types[name] = new Type(BNNewTypeReference(result.types[i].type)); + } for (size_t i = 0; i < result.variableCount; i++) - types[result.variables[i].name] = new Type(BNNewTypeReference(result.variables[i].type)); + { + vector name; + for (size_t j = 0; j < result.variables[i].nameCount; j++) + name.push_back(result.variables[i].name[j]); + types[name] = new Type(BNNewTypeReference(result.variables[i].type)); + } for (size_t i = 0; i < result.functionCount; i++) - types[result.functions[i].name] = new Type(BNNewTypeReference(result.functions[i].type)); + { + vector name; + for (size_t j = 0; j < result.functions[i].nameCount; j++) + name.push_back(result.functions[i].name[j]); + types[name] = new Type(BNNewTypeReference(result.functions[i].type)); + } BNFreeTypeParserResult(&result); return true; } -bool Architecture::ParseTypesFromSourceFile(const string& fileName, map>& types, - map>& variables, map>& functions, - string& errors, const vector& includeDirs) +bool Architecture::ParseTypesFromSourceFile(const string& fileName, map, Ref>& types, + map, Ref>& variables, map, Ref>& functions, + string& errors, const vector& includeDirs) { BNTypeParserResult result; char* errorStr; @@ -795,18 +809,33 @@ bool Architecture::ParseTypesFromSourceFile(const string& fileName, map name; + for (size_t j = 0; j < result.types[i].nameCount; j++) + name.push_back(result.types[i].name[j]); + types[name] = new Type(BNNewTypeReference(result.types[i].type)); + } for (size_t i = 0; i < result.variableCount; i++) - variables[result.variables[i].name] = new Type(BNNewTypeReference(result.variables[i].type)); + { + vector name; + for (size_t j = 0; j < result.variables[i].nameCount; j++) + name.push_back(result.variables[i].name[j]); + variables[name] = new Type(BNNewTypeReference(result.variables[i].type)); + } for (size_t i = 0; i < result.functionCount; i++) - functions[result.functions[i].name] = new Type(BNNewTypeReference(result.functions[i].type)); + { + vector name; + for (size_t j = 0; j < result.functions[i].nameCount; j++) + name.push_back(result.functions[i].name[j]); + functions[name] = new Type(BNNewTypeReference(result.functions[i].type)); + } BNFreeTypeParserResult(&result); return true; } diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 58f901ab..15c86a58 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -590,8 +590,8 @@ namespace BinaryNinja static void DataVariableUpdatedCallback(void* ctxt, BNBinaryView* data, BNDataVariable* var); static void StringFoundCallback(void* ctxt, BNBinaryView* data, BNStringType type, uint64_t offset, size_t len); static void StringRemovedCallback(void* ctxt, BNBinaryView* data, BNStringType type, uint64_t offset, size_t len); - static void TypeDefinedCallback(void* ctxt, BNBinaryView* data, const char* name, BNType* type); - static void TypeUndefinedCallback(void* ctxt, BNBinaryView* data, const char* name, BNType* type); + static void TypeDefinedCallback(void* ctxt, BNBinaryView* data, const char** name, size_t nameCount, BNType* type); + static void TypeUndefinedCallback(void* ctxt, BNBinaryView* data, const char** name, size_t nameCount, BNType* type); public: BinaryDataNotification(); @@ -610,8 +610,8 @@ namespace BinaryNinja virtual void OnDataVariableUpdated(BinaryView* view, const DataVariable& var) { (void)view; (void)var; } virtual void OnStringFound(BinaryView* data, BNStringType type, uint64_t offset, size_t len) { (void)data; (void)type; (void)offset; (void)len; } virtual void OnStringRemoved(BinaryView* data, BNStringType type, uint64_t offset, size_t len) { (void)data; (void)type; (void)offset; (void)len; } - virtual void OnTypeDefined(BinaryView* data, const std::string& name, Type* type) { (void)data; (void)name; (void)type; } - virtual void OnTypeUndefined(BinaryView* data, const std::string& name, Type* type) { (void)data; (void)name; (void)type; } + virtual void OnTypeDefined(BinaryView* data, const std::vector& name, Type* type) { (void)data; (void)name; (void)type; } + virtual void OnTypeUndefined(BinaryView* data, const std::vector& name, Type* type) { (void)data; (void)name; (void)type; } }; class FileAccessor @@ -755,7 +755,7 @@ namespace BinaryNinja uint64_t align, entrySize; }; - struct NameAndType; + struct QualifiedNameAndType; /*! BinaryView is the base class for creating views on binary data (e.g. ELF, PE, Mach-O). BinaryView should be subclassed to create a new BinaryView @@ -977,15 +977,21 @@ namespace BinaryNinja std::vector GetNextLinearDisassemblyLines(LinearDisassemblyPosition& pos, DisassemblySettings* settings); - bool ParseTypeString(const std::string& text, NameAndType& result, std::string& errors); + bool ParseTypeString(const std::string& text, QualifiedNameAndType& result, std::string& errors); - std::map> GetTypes(); + std::map, Ref> GetTypes(); Ref GetTypeByName(const std::string& name); + Ref GetTypeByName(const std::vector& name); bool IsTypeAutoDefined(const std::string& name); + bool IsTypeAutoDefined(const std::vector& name); void DefineType(const std::string& name, Ref type); + void DefineType(const std::vector& name, Ref type); void DefineUserType(const std::string& name, Ref type); + void DefineUserType(const std::vector& name, Ref type); void UndefineType(const std::string& name); + void UndefineType(const std::vector& name); void UndefineUserType(const std::string& name); + void UndefineUserType(const std::vector& name); bool FindNextData(uint64_t start, const DataBuffer& data, uint64_t& result, BNFindFlag flags = NoFindFlags); @@ -1435,13 +1441,15 @@ namespace BinaryNinja void SetBinaryViewTypeConstant(const std::string& type, const std::string& name, uint64_t value); bool ParseTypesFromSource(const std::string& source, const std::string& fileName, - std::map>& types, std::map>& variables, - std::map>& functions, std::string& errors, - const std::vector& includeDirs = std::vector()); - bool ParseTypesFromSourceFile(const std::string& fileName, std::map>& types, - std::map>& variables, - std::map>& functions, std::string& errors, - const std::vector& includeDirs = std::vector()); + std::map, Ref>& types, + std::map, Ref>& variables, + std::map, Ref>& functions, std::string& errors, + const std::vector& includeDirs = std::vector()); + bool ParseTypesFromSourceFile(const std::string& fileName, + std::map, Ref>& types, + std::map, Ref>& variables, + std::map, Ref>& functions, std::string& errors, + const std::vector& includeDirs = std::vector()); void RegisterCallingConvention(CallingConvention* cc); std::vector> GetCallingConventions(); @@ -1504,7 +1512,7 @@ namespace BinaryNinja }; class Structure; - class UnknownType; + class NamedTypeReference; class Enumeration; struct NameAndType @@ -1513,6 +1521,12 @@ namespace BinaryNinja Ref type; }; + struct QualifiedNameAndType + { + std::vector name; + Ref type; + }; + class Type: public CoreRefCountObject { public: @@ -1532,7 +1546,7 @@ namespace BinaryNinja bool CanReturn() const; Ref GetStructure() const; Ref GetEnumeration() const; - Ref GetUnknownType() const; + Ref GetNamedTypeReference() const; uint64_t GetElementCount() const; @@ -1554,7 +1568,8 @@ namespace BinaryNinja static Ref IntegerType(size_t width, bool sign, const std::string& altName = ""); static Ref FloatType(size_t width, const std::string& typeName = ""); static Ref StructureType(Structure* strct); - static Ref UnknownNamedType(UnknownType* unknwn); + static Ref NamedType(NamedTypeReference* ref, size_t width = 0, size_t align = 1); + static Ref NamedType(const std::vector& name, Type* type); static Ref EnumerationType(Architecture* arch, Enumeration* enm, size_t width = 0, bool issigned = false); static Ref PointerType(Architecture* arch, Type* type, bool cnst = false, bool vltl = false, BNReferenceType refType = PointerReferenceType); @@ -1565,10 +1580,14 @@ namespace BinaryNinja static std::string GetQualifiedName(const std::vector& names); }; - class UnknownType: public CoreRefCountObject + class NamedTypeReference: public CoreRefCountObject { public: - UnknownType(BNUnknownType* s, std::vector name = {}); + NamedTypeReference(BNNamedTypeReference* nt); + NamedTypeReference(BNNamedTypeReferenceClass cls, const std::vector& name = {}); + BNNamedTypeReferenceClass GetTypeClass() const; + void SetTypeClass(BNNamedTypeReferenceClass cls); std::vector GetName() const; void SetName(const std::vector& name); }; @@ -1586,8 +1605,6 @@ namespace BinaryNinja Structure(); Structure(BNStructure* s); - std::vector GetName() const; - void SetName(const std::vector& name); std::vector GetMembers() const; uint64_t GetWidth() const; void SetWidth(size_t width); @@ -1616,9 +1633,6 @@ namespace BinaryNinja public: Enumeration(BNEnumeration* e); - std::vector GetName() const; - void SetName(const std::vector& name); - std::vector GetMembers() const; void AddMember(const std::string& name); diff --git a/binaryninjacore.h b/binaryninjacore.h index b29a67a2..26f37536 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -94,7 +94,7 @@ extern "C" struct BNLowLevelILFunction; struct BNType; struct BNStructure; - struct BNUnknownType; + struct BNNamedTypeReference; struct BNEnumeration; struct BNCallingConvention; struct BNPlatform; @@ -371,7 +371,17 @@ extern "C" FunctionTypeClass = 8, VarArgsTypeClass = 9, ValueTypeClass = 10, - UnknownTypeClass = 11 + NamedTypeReferenceClass = 11 + }; + + enum BNNamedTypeReferenceClass + { + UnknownNamedTypeClass = 0, + TypedefNamedTypeClass = 1, + ClassNamedTypeClass = 2, + StructNamedTypeClass = 3, + UnionNamedTypeClass = 4, + EnumNamedTypeClass = 5 }; enum BNStructureType @@ -635,8 +645,8 @@ extern "C" void (*dataVariableUpdated)(void* ctxt, BNBinaryView* view, BNDataVariable* var); void (*stringFound)(void* ctxt, BNBinaryView* view, BNStringType type, uint64_t offset, size_t len); void (*stringRemoved)(void* ctxt, BNBinaryView* view, BNStringType type, uint64_t offset, size_t len); - void (*typeDefined)(void* ctxt, BNBinaryView* view, const char* name, BNType* type); - void (*typeUndefined)(void* ctxt, BNBinaryView* view, const char* name, BNType* type); + void (*typeDefined)(void* ctxt, BNBinaryView* view, const char** name, size_t nameCount, BNType* type); + void (*typeUndefined)(void* ctxt, BNBinaryView* view, const char** name, size_t nameCount, BNType* type); }; struct BNFileAccessor @@ -842,6 +852,13 @@ extern "C" BNType* type; }; + struct BNQualifiedNameAndType + { + char** name; + size_t nameCount; + BNType* type; + }; + struct BNStructureMember { BNType* type; @@ -864,9 +881,9 @@ extern "C" struct BNTypeParserResult { - BNNameAndType* types; - BNNameAndType* variables; - BNNameAndType* functions; + BNQualifiedNameAndType* types; + BNQualifiedNameAndType* variables; + BNQualifiedNameAndType* functions; size_t typeCount, variableCount, functionCount; }; @@ -1776,17 +1793,19 @@ extern "C" BINARYNINJACOREAPI void BNFreeDataVariables(BNDataVariable* vars, size_t count); BINARYNINJACOREAPI bool BNGetDataVariableAtAddress(BNBinaryView* view, uint64_t addr, BNDataVariable* var); - BINARYNINJACOREAPI bool BNParseTypeString(BNBinaryView* view, const char* text, BNNameAndType* result, char** errors); + BINARYNINJACOREAPI bool BNParseTypeString(BNBinaryView* view, const char* text, + BNQualifiedNameAndType* result, char** errors); BINARYNINJACOREAPI void BNFreeNameAndType(BNNameAndType* obj); + BINARYNINJACOREAPI void BNFreeQualifiedNameAndType(BNQualifiedNameAndType* obj); - BINARYNINJACOREAPI BNNameAndType* BNGetAnalysisTypeList(BNBinaryView* view, size_t* count); - BINARYNINJACOREAPI void BNFreeTypeList(BNNameAndType* types, size_t count); - BINARYNINJACOREAPI BNType* BNGetAnalysisTypeByName(BNBinaryView* view, const char* name); - BINARYNINJACOREAPI bool BNIsAnalysisTypeAutoDefined(BNBinaryView* view, const char* name); - BINARYNINJACOREAPI void BNDefineAnalysisType(BNBinaryView* view, const char* name, BNType* type); - BINARYNINJACOREAPI void BNDefineUserAnalysisType(BNBinaryView* view, const char* name, BNType* type); - BINARYNINJACOREAPI void BNUndefineAnalysisType(BNBinaryView* view, const char* name); - BINARYNINJACOREAPI void BNUndefineUserAnalysisType(BNBinaryView* view, const char* name); + BINARYNINJACOREAPI BNQualifiedNameAndType* BNGetAnalysisTypeList(BNBinaryView* view, size_t* count); + BINARYNINJACOREAPI void BNFreeTypeList(BNQualifiedNameAndType* types, size_t count); + BINARYNINJACOREAPI BNType* BNGetAnalysisTypeByName(BNBinaryView* view, const char** name, size_t nameCount); + BINARYNINJACOREAPI bool BNIsAnalysisTypeAutoDefined(BNBinaryView* view, const char** name, size_t nameCount); + BINARYNINJACOREAPI void BNDefineAnalysisType(BNBinaryView* view, const char** name, size_t nameCount, BNType* type); + BINARYNINJACOREAPI void BNDefineUserAnalysisType(BNBinaryView* view, const char** name, size_t nameCount, BNType* type); + BINARYNINJACOREAPI void BNUndefineAnalysisType(BNBinaryView* view, const char** name, size_t nameCount); + BINARYNINJACOREAPI void BNUndefineUserAnalysisType(BNBinaryView* view, const char** name, size_t nameCount); BINARYNINJACOREAPI void BNReanalyzeAllFunctions(BNBinaryView* view); BINARYNINJACOREAPI void BNReanalyzeFunction(BNFunction* func); @@ -1968,6 +1987,7 @@ extern "C" BINARYNINJACOREAPI bool BNFunctionTypeCanReturn(BNType* type); BINARYNINJACOREAPI BNStructure* BNGetTypeStructure(BNType* type); BINARYNINJACOREAPI BNEnumeration* BNGetTypeEnumeration(BNType* type); + BINARYNINJACOREAPI BNNamedTypeReference* BNGetTypeNamedTypeReference(BNType* type); BINARYNINJACOREAPI uint64_t BNGetTypeElementCount(BNType* type); BINARYNINJACOREAPI void BNSetFunctionCanReturn(BNType* type, bool canReturn); @@ -1979,19 +1999,20 @@ extern "C" BINARYNINJACOREAPI BNInstructionTextToken* BNGetTypeTokensAfterName(BNType* type, size_t* count); BINARYNINJACOREAPI void BNFreeTokenList(BNInstructionTextToken* tokens, size_t count); - BINARYNINJACOREAPI BNType* BNCreateUnknownNamedType(BNUnknownType* ut); - BINARYNINJACOREAPI BNUnknownType* BNCreateUnknownType(void); - BINARYNINJACOREAPI void BNSetUnknownTypeName(BNUnknownType* ut, const char** name, size_t size); - BINARYNINJACOREAPI char** BNGetUnknownTypeName(BNUnknownType* ut, size_t* size); - BINARYNINJACOREAPI void BNFreeUnknownType(BNUnknownType* ut); - BINARYNINJACOREAPI BNUnknownType* BNNewUnknownTypeReference(BNUnknownType* ut); + BINARYNINJACOREAPI BNType* BNCreateNamedTypeReference(BNNamedTypeReference* nt, size_t width, size_t align); + BINARYNINJACOREAPI BNType* BNCreateNamedTypeReferenceFromType(const char** name, size_t nameCount, BNType* type); + BINARYNINJACOREAPI BNNamedTypeReference* BNCreateNamedType(void); + BINARYNINJACOREAPI void BNSetTypeReferenceClass(BNNamedTypeReference* nt, BNNamedTypeReferenceClass cls); + BINARYNINJACOREAPI BNNamedTypeReferenceClass BNGetTypeReferenceClass(BNNamedTypeReference* nt); + BINARYNINJACOREAPI void BNSetTypeReferenceName(BNNamedTypeReference* nt, const char** name, size_t size); + BINARYNINJACOREAPI char** BNGetTypeReferenceName(BNNamedTypeReference* nt, size_t* size); + BINARYNINJACOREAPI void BNFreeNamedTypeReference(BNNamedTypeReference* nt); + BINARYNINJACOREAPI BNNamedTypeReference* BNNewNamedTypeReference(BNNamedTypeReference* nt); BINARYNINJACOREAPI BNStructure* BNCreateStructure(void); BINARYNINJACOREAPI BNStructure* BNNewStructureReference(BNStructure* s); BINARYNINJACOREAPI void BNFreeStructure(BNStructure* s); - BINARYNINJACOREAPI char** BNGetStructureName(BNStructure* s, size_t* size); - BINARYNINJACOREAPI void BNSetStructureName(BNStructure* s, const char** names, size_t size); BINARYNINJACOREAPI BNStructureMember* BNGetStructureMembers(BNStructure* s, size_t* count); BINARYNINJACOREAPI void BNFreeStructureMemberList(BNStructureMember* members, size_t count); BINARYNINJACOREAPI uint64_t BNGetStructureWidth(BNStructure* s); @@ -2012,8 +2033,6 @@ extern "C" BINARYNINJACOREAPI BNEnumeration* BNNewEnumerationReference(BNEnumeration* e); BINARYNINJACOREAPI void BNFreeEnumeration(BNEnumeration* e); - BINARYNINJACOREAPI char** BNGetEnumerationName(BNEnumeration* e, size_t* size); - BINARYNINJACOREAPI void BNSetEnumerationName(BNEnumeration* e, const char** name, size_t size); BINARYNINJACOREAPI BNEnumerationMember* BNGetEnumerationMembers(BNEnumeration* e, size_t* count); BINARYNINJACOREAPI void BNFreeEnumerationMemberList(BNEnumerationMember* members, size_t count); diff --git a/binaryview.cpp b/binaryview.cpp index 154dfcf5..9fdd5748 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -129,21 +129,29 @@ void BinaryDataNotification::StringRemovedCallback(void* ctxt, BNBinaryView* obj } -void BinaryDataNotification::TypeDefinedCallback(void* ctxt, BNBinaryView* data, const char* name, BNType* type) +void BinaryDataNotification::TypeDefinedCallback(void* ctxt, BNBinaryView* data, const char** name, size_t nameCount, + BNType* type) { BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; Ref view = new BinaryView(BNNewViewReference(data)); Ref typeObj = new Type(BNNewTypeReference(type)); - notify->OnTypeDefined(view, name, typeObj); + vector nameList; + for (size_t i = 0; i < nameCount; i++) + nameList.push_back(name[i]); + notify->OnTypeDefined(view, nameList, typeObj); } -void BinaryDataNotification::TypeUndefinedCallback(void* ctxt, BNBinaryView* data, const char* name, BNType* type) +void BinaryDataNotification::TypeUndefinedCallback(void* ctxt, BNBinaryView* data, const char** name, size_t nameCount, + BNType* type) { BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; Ref view = new BinaryView(BNNewViewReference(data)); Ref typeObj = new Type(BNNewTypeReference(type)); - notify->OnTypeUndefined(view, name, typeObj); + vector nameList; + for (size_t i = 0; i < nameCount; i++) + nameList.push_back(name[i]); + notify->OnTypeUndefined(view, nameList, typeObj); } @@ -1447,9 +1455,9 @@ vector BinaryView::GetNextLinearDisassemblyLines(LinearDi } -bool BinaryView::ParseTypeString(const string& text, NameAndType& result, string& errors) +bool BinaryView::ParseTypeString(const string& text, QualifiedNameAndType& result, string& errors) { - BNNameAndType nt; + BNQualifiedNameAndType nt; char* errorStr; if (!BNParseTypeString(m_object, text.c_str(), &nt, &errorStr)) @@ -1459,22 +1467,28 @@ bool BinaryView::ParseTypeString(const string& text, NameAndType& result, string return false; } - result.name = nt.name; - result.type = new Type(nt.type); + for (size_t i = 0; i < nt.nameCount; i++) + result.name.push_back(nt.name[i]); + result.type = new Type(BNNewTypeReference(nt.type)); errors = ""; - BNFreeString(nt.name); + BNFreeQualifiedNameAndType(&nt); return true; } -map> BinaryView::GetTypes() +map, Ref> BinaryView::GetTypes() { size_t count; - BNNameAndType* types = BNGetAnalysisTypeList(m_object, &count); + BNQualifiedNameAndType* types = BNGetAnalysisTypeList(m_object, &count); - map> result; + map, Ref> result; for (size_t i = 0; i < count; i++) - result[types[i].name] = new Type(BNNewTypeReference(types[i].type)); + { + vector name; + for (size_t j = 0; j < types[i].nameCount; j++) + name.push_back(types[i].name[j]); + result[name] = new Type(BNNewTypeReference(types[i].type)); + } BNFreeTypeList(types, count); return result; @@ -1483,40 +1497,112 @@ map> BinaryView::GetTypes() Ref BinaryView::GetTypeByName(const string& name) { - BNType* type = BNGetAnalysisTypeByName(m_object, name.c_str()); + const char* nameStr = name.c_str(); + BNType* type = BNGetAnalysisTypeByName(m_object, &nameStr, 1); + if (!type) + return nullptr; + return new Type(type); +} + + +Ref BinaryView::GetTypeByName(const vector& name) +{ + const char** nameList = new const char*[name.size()]; + for (size_t i = 0; i < name.size(); i++) + nameList[i] = name[i].c_str(); + + BNType* type = BNGetAnalysisTypeByName(m_object, nameList, name.size()); + delete[] nameList; + if (!type) return nullptr; return new Type(type); } -bool BinaryView::IsTypeAutoDefined(const std::string& name) +bool BinaryView::IsTypeAutoDefined(const string& name) +{ + const char* nameStr = name.c_str(); + return BNIsAnalysisTypeAutoDefined(m_object, &nameStr, 1); +} + + +bool BinaryView::IsTypeAutoDefined(const vector& name) +{ + const char** nameList = new const char*[name.size()]; + for (size_t i = 0; i < name.size(); i++) + nameList[i] = name[i].c_str(); + bool result = BNIsAnalysisTypeAutoDefined(m_object, nameList, name.size()); + delete[] nameList; + return result; +} + + +void BinaryView::DefineType(const string& name, Ref type) +{ + const char* nameStr = name.c_str(); + BNDefineAnalysisType(m_object, &nameStr, 1, type->GetObject()); +} + + +void BinaryView::DefineType(const vector& name, Ref type) +{ + const char** nameList = new const char*[name.size()]; + for (size_t i = 0; i < name.size(); i++) + nameList[i] = name[i].c_str(); + BNDefineAnalysisType(m_object, nameList, name.size(), type->GetObject()); + delete[] nameList; +} + + +void BinaryView::DefineUserType(const string& name, Ref type) +{ + const char* nameStr = name.c_str(); + BNDefineUserAnalysisType(m_object, &nameStr, 1, type->GetObject()); +} + + +void BinaryView::DefineUserType(const vector& name, Ref type) { - return BNIsAnalysisTypeAutoDefined(m_object, name.c_str()); + const char** nameList = new const char*[name.size()]; + for (size_t i = 0; i < name.size(); i++) + nameList[i] = name[i].c_str(); + BNDefineUserAnalysisType(m_object, nameList, name.size(), type->GetObject()); + delete[] nameList; } -void BinaryView::DefineType(const std::string& name, Ref type) +void BinaryView::UndefineType(const string& name) { - BNDefineAnalysisType(m_object, name.c_str(), type->GetObject()); + const char* nameStr = name.c_str(); + BNUndefineAnalysisType(m_object, &nameStr, 1); } -void BinaryView::DefineUserType(const std::string& name, Ref type) +void BinaryView::UndefineType(const vector& name) { - BNDefineUserAnalysisType(m_object, name.c_str(), type->GetObject()); + const char** nameList = new const char*[name.size()]; + for (size_t i = 0; i < name.size(); i++) + nameList[i] = name[i].c_str(); + BNUndefineAnalysisType(m_object, nameList, name.size()); + delete[] nameList; } -void BinaryView::UndefineType(const std::string& name) +void BinaryView::UndefineUserType(const string& name) { - BNUndefineAnalysisType(m_object, name.c_str()); + const char* nameStr = name.c_str(); + BNUndefineUserAnalysisType(m_object, &nameStr, 1); } -void BinaryView::UndefineUserType(const std::string& name) +void BinaryView::UndefineUserType(const vector& name) { - BNUndefineUserAnalysisType(m_object, name.c_str()); + const char** nameList = new const char*[name.size()]; + for (size_t i = 0; i < name.size(); i++) + nameList[i] = name[i].c_str(); + BNUndefineUserAnalysisType(m_object, nameList, name.size()); + delete[] nameList; } diff --git a/python/__init__.py b/python/__init__.py index cc138009..b5ced583 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -660,6 +660,70 @@ class StringReference(object): def __repr__(self): return "<%s: %#x, len %#x>" % (self.type, self.start, self.length) +class QualifiedName(object): + def __init__(self, name = []): + if isinstance(name, str): + self.name = [name] + else: + self.name = name + + def __str__(self): + return "::".join(self.name) + + def __repr__(self): + return repr(str(self)) + + def __len__(self): + return len(self.name) + + def __hash__(self): + return hash(str(self)) + + def __eq__(self, other): + if isinstance(other, str): + return str(self) == other + elif isinstance(other, list): + return self.name == other + elif isinstance(other, QualifiedName): + return self.name == other.name + return False + + def __ne__(self, other): + return not (self == other) + + def __lt__(self, other): + if isinstance(other, QualifiedName): + return self.name < other.name + return False + + def __le__(self, other): + if isinstance(other, QualifiedName): + return self.name <= other.name + return False + + def __gt__(self, other): + if isinstance(other, QualifiedName): + return self.name > other.name + return False + + def __ge__(self, other): + if isinstance(other, QualifiedName): + return self.name >= other.name + return False + + def __cmp__(self, other): + if self == other: + return 0 + if self < other: + return -1 + return 1 + + def __getitem__(self, key): + return self.name[key] + + def __iter__(self): + return iter(self.name) + class BinaryDataNotificationCallbacks(object): def __init__(self, view, notify): self.view = view @@ -761,15 +825,21 @@ class BinaryDataNotificationCallbacks(object): except: log_error(traceback.format_exc()) - def _type_defined(self, ctxt, name, type_obj): + def _type_defined(self, ctxt, name, name_count, type_obj): try: - self.notify.type_defined(self.view, name, Type(core.BNNewTypeReference(type_obj))) + name_list = [] + for i in xrange(0, name_count): + name_list.append(name[i]) + self.notify.type_defined(self.view, QualifiedName(name_list), Type(core.BNNewTypeReference(type_obj))) except: log_error(traceback.format_exc()) - def _type_undefined(self, ctxt, name, type_obj): + def _type_undefined(self, ctxt, name, name_count, type_obj): try: - self.notify.type_undefined(self.view, name, Type(core.BNNewTypeReference(type_obj))) + name_list = [] + for i in xrange(0, name_count): + name_list.append(name[i]) + self.notify.type_undefined(self.view, QualifiedName(name_list), Type(core.BNNewTypeReference(type_obj))) except: log_error(traceback.format_exc()) @@ -1394,7 +1464,10 @@ class BinaryView(object): type_list = core.BNGetAnalysisTypeList(self.handle, count) result = {} for i in xrange(0, count.value): - result[type_list[i].name] = Type(core.BNNewTypeReference(type_list[i].type)) + name = [] + for j in xrange(0, type_list[i].nameCount): + name.append(type_list[i].name[j]) + result[QualifiedName(name)] = Type(core.BNNewTypeReference(type_list[i].type)) core.BNFreeTypeList(type_list, count.value) return result @@ -3350,30 +3423,33 @@ class BinaryView(object): ``parse_type_string`` converts `C-style` string into a :py:Class:`Type`. :param str text: `C-style` string of type to create - :return: A tuple of a :py:Class:`Type` and string type name - :rtype: tuple(Type, str) + :return: A tuple of a :py:Class:`Type` and type name + :rtype: tuple(Type, QualifiedName) :Example: >>> bv.parse_type_string("int foo") (, 'foo') >>> """ - result = core.BNNameAndType() + result = core.BNQualifiedNameAndType() errors = ctypes.c_char_p() if not core.BNParseTypeString(self.handle, text, result, errors): error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) raise SyntaxError, error_str type_obj = Type(core.BNNewTypeReference(result.type)) - name = result.name - core.BNFreeNameAndType(result) + name = [] + for i in xrange(0, result.nameCount): + name.append(result.name[i]) + name = QualifiedName(name) + core.BNFreeQualifiedNameAndType(result) return type_obj, name def get_type_by_name(self, name): """ ``get_type_by_name`` returns the defined type whose name corresponds with the provided ``name`` - :param str name: Type name to lookup + :param QualifiedName name: Type name to lookup :return: A :py:Class:`Type` or None if the type does not exist :rtype: Type or None :Example: @@ -3384,7 +3460,12 @@ class BinaryView(object): >>> """ - obj = core.BNGetAnalysisTypeByName(self.handle, name) + if isinstance(name, str): + name = [name] + name_list = (ctypes.c_char_p * len(name))() + for i in xrange(0, len(name)): + name_list[i] = name[i] + obj = core.BNGetAnalysisTypeByName(self.handle, name_list, len(name)) if not obj: return None return Type(obj) @@ -3394,7 +3475,7 @@ class BinaryView(object): ``is_type_auto_defined`` queries the user type list of name. If name is not in the *user* type list then the name is considered an *auto* type. - :param str name: Name of type to query + :param QualifiedName name: Name of type to query :return: True if the type is not a *user* type. False if the type is a *user* type. :Example: >>> bv.is_type_auto_defined("foo") @@ -3404,14 +3485,19 @@ class BinaryView(object): False >>> """ - return core.BNIsAnalysisTypeAutoDefined(self.handle, name) + if isinstance(name, str): + name = [name] + name_list = (ctypes.c_char_p * len(name))() + for i in xrange(0, len(name)): + name_list[i] = name[i] + return core.BNIsAnalysisTypeAutoDefined(self.handle, name_list, len(name)) def define_type(self, name, type_obj): """ ``define_type`` registers a :py:Class:`Type` ``type_obj`` of the given ``name`` in the global list of types for the current :py:Class:`BinaryView`. - :param str name: Name of the type to be registered + :param QualifiedName name: Name of the type to be registered :param Type type_obj: Type object to be registered :rtype: None :Example: @@ -3421,14 +3507,19 @@ class BinaryView(object): >>> bv.get_type_by_name(name) """ - core.BNDefineAnalysisType(self.handle, name, type_obj.handle) + if isinstance(name, str): + name = [name] + name_list = (ctypes.c_char_p * len(name))() + for i in xrange(0, len(name)): + name_list[i] = name[i] + core.BNDefineAnalysisType(self.handle, name_list, len(name), type_obj.handle) def define_user_type(self, name, type_obj): """ ``define_user_type`` registers a :py:Class:`Type` ``type_obj`` of the given ``name`` in the global list of user types for the current :py:Class:`BinaryView`. - :param str name: Name of the user type to be registered + :param QualifiedName name: Name of the user type to be registered :param Type type_obj: Type object to be registered :rtype: None :Example: @@ -3438,13 +3529,18 @@ class BinaryView(object): >>> bv.get_type_by_name(name) """ - core.BNDefineUserAnalysisType(self.handle, name, type_obj.handle) + if isinstance(name, str): + name = [name] + name_list = (ctypes.c_char_p * len(name))() + for i in xrange(0, len(name)): + name_list[i] = name[i] + core.BNDefineUserAnalysisType(self.handle, name_list, len(name), type_obj.handle) def undefine_type(self, name): """ ``undefine_type`` removes a :py:Class:`Type` from the global list of types for the current :py:Class:`BinaryView` - :param str name: Name of type to be undefined + :param QualifiedName name: Name of type to be undefined :rtype: None :Example: @@ -3456,14 +3552,19 @@ class BinaryView(object): >>> bv.get_type_by_name(name) >>> """ - core.BNUndefineAnalysisType(self.handle, name) + if isinstance(name, str): + name = [name] + name_list = (ctypes.c_char_p * len(name))() + for i in xrange(0, len(name)): + name_list[i] = name[i] + core.BNUndefineAnalysisType(self.handle, name_list, len(name)) def undefine_user_type(self, name): """ ``undefine_user_type`` removes a :py:Class:`Type` from the global list of user types for the current :py:Class:`BinaryView` - :param str name: Name of user type to be undefined + :param QualifiedName name: Name of user type to be undefined :rtype: None :Example: @@ -3475,7 +3576,12 @@ class BinaryView(object): >>> bv.get_type_by_name(name) >>> """ - core.BNUndefineUserAnalysisType(self.handle, name) + if isinstance(name, str): + name = [name] + name_list = (ctypes.c_char_p * len(name))() + for i in xrange(0, len(name)): + name_list[i] = name[i] + core.BNUndefineUserAnalysisType(self.handle, name_list, len(name)) def find_next_data(self, start, data, flags = 0): """ @@ -4313,6 +4419,14 @@ class Type(object): return None return Enumeration(result) + @property + def named_type_reference(self): + """Reference to a named type (read-only)""" + result = core.BNGetTypeNamedTypeReference(self.handle) + if result is None: + return None + return NamedTypeReference(result) + @property def count(self): """Type count (read-only)""" @@ -4351,12 +4465,19 @@ class Type(object): return Type(core.BNCreateStructureType(structure_type.handle)) @classmethod - def unknown_type(self, unknown_type): - return Type(core.BNCreateUnknownType(unknown_type.handle)) + def named_type(self, named_type, width = 0, align = 1): + return Type(core.BNCreateNamedTypeReference(named_type.handle, width, align)) @classmethod - def unknown_type(self, s): - return Type(core.BNCreateUnknownType(s.handle)) + def named_type_from_type(self, name, t): + if isinstance(name, str): + name = [name] + name_list = (ctypes.c_char_p * len(name))() + for i in xrange(0, len(name)): + name_list[i] = name[i] + if t is not None: + t = t.handle + return Type(core.BNCreateNamedTypeReferenceFromType(name_list, len(name), t)) @classmethod def enumeration_type(self, arch, e, width = None): @@ -4394,28 +4515,60 @@ class Type(object): raise AttributeError, "attribute '%s' is read only" % name -class UnknownType(object): - def __init__(self, handle = None): +class NamedTypeReference(object): + def __init__(self, type_class = core.UnknownNamedTypeClass, name = None, handle = None): if handle is None: - self.handle = core.BNCreateUnknownType() + self.handle = core.BNCreateNamedType() + core.BNSetTypeReferenceClass(self.handle, type_class) + if name is not None: + if isinstance(name, str): + name = [name] + name_list = (ctypes.c_char_p * len(name))() + for i in xrange(0, len(name)): + name_list[i] = name[i] + core.BNSetTypeReferenceName(self.handle, name_list, len(name)) else: self.handle = handle def __del__(self): - core.BNFreeUnknownType(self.handle) + core.BNFreeNamedTypeReference(self.handle) + + @property + def type_class(self): + return core.BNGetTypeReferenceClass(self.handle) + + @type_class.setter + def type_class(self, value): + core.BNSetTypeReferenceClass(self.handle, value) @property def name(self): count = ctypes.c_ulonglong() - nameList = core.BNGetUnknownTypeName(self.handle, count) + nameList = core.BNGetTypeReferenceName(self.handle, count) result = [] for i in xrange(count.value): result.append(nameList[i]) - return get_qualified_name(result) + return QualifiedName(result) @name.setter def name(self, value): - core.BNSetUnknownTypeName(self.handle, value) + if isinstance(value, str): + value = [value] + name_list = (ctypes.c_char_p * len(value))() + for i in xrange(0, len(value)): + name_list[i] = value[i] + core.BNSetTypeReferenceName(self.handle, name_list, len(value)) + + def __repr__(self): + if self.type_class == core.TypedefNamedTypeClass: + return "" % str(self.name) + if self.type_class == core.StructNamedTypeClass: + return "" % str(self.name) + if self.type_class == core.UnionNamedTypeClass: + return "" % str(self.name) + if self.type_class == core.EnumNamedTypeClass: + return "" % str(self.name) + return "" % str(self.name) class StructureMember(object): @@ -4440,19 +4593,6 @@ class Structure(object): def __del__(self): core.BNFreeStructure(self.handle) - @property - def name(self): - count = ctypes.c_ulonglong() - nameList = core.BNGetStructureName(self.handle, count) - result = [] - for i in xrange(count.value): - result.append(nameList[i]) - return get_qualified_name(result) - - @name.setter - def name(self, value): - core.BNSetStructureName(self.handle, value) - @property def members(self): """Structure member list (read-only)""" @@ -4538,14 +4678,6 @@ class Enumeration(object): def __del__(self): core.BNFreeEnumeration(self.handle) - @property - def name(self): - return core.BNGetEnumerationName(self.handle) - - @name.setter - def name(self, value): - core.BNSetEnumerationName(self.handle, value) - @property def members(self): """Enumeration member list (read-only)""" @@ -7423,8 +7555,8 @@ class Architecture(object): :param str source: source string to be parsed :param str filename: optional source filename :param list(str) include_dirs: optional list of string filename include directories - :return: a tuple of py:class:`TypeParserResult` and error string - :rtype: tuple(TypeParserResult,str) + :return: py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) + :rtype: TypeParserResult :Example: >>> arch.parse_types_from_source('int foo;\\nint bar(int x);\\nstruct bas{int x,y;};\\n') @@ -7444,18 +7576,27 @@ class Architecture(object): error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) if not result: - return (None, error_str) + raise SyntaxError, error_str types = {} variables = {} functions = {} for i in xrange(0, parse.typeCount): - types[parse.types[i].name] = Type(core.BNNewTypeReference(parse.types[i].type)) + name = [] + for j in xrange(0, parse.types[i].nameCount): + name.append(parse.types[i].name[j]) + types[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.types[i].type)) for i in xrange(0, parse.variableCount): - variables[parse.variables[i].name] = Type(core.BNNewTypeReference(parse.variables[i].type)) + name = [] + for j in xrange(0, parse.variables[i].nameCount): + name.append(parse.variables[i].name[j]) + variables[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.variables[i].type)) for i in xrange(0, parse.functionCount): - functions[parse.functions[i].name] = Type(core.BNNewTypeReference(parse.functions[i].type)) - BNFreeTypeParserResult(parse) - return (TypeParserResult(types, variables, functions), error_str) + name = [] + for j in xrange(0, parse.functions[i].nameCount): + name.append(parse.functions[i].name[j]) + functions[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.functions[i].type)) + core.BNFreeTypeParserResult(parse) + return TypeParserResult(types, variables, functions) def parse_types_from_source_file(self, filename, include_dirs = []): """ @@ -7464,8 +7605,8 @@ class Architecture(object): :param str filename: filename of file to be parsed :param list(str) include_dirs: optional list of string filename include directories - :return: a tuple of py:class:`TypeParserResult` and error string - :rtype: tuple(TypeParserResult, str) + :return: py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) + :rtype: TypeParserResult :Example: >>> file = "/Users/binja/tmp.c" @@ -7485,18 +7626,27 @@ class Architecture(object): error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) if not result: - return (None, error_str) + raise SyntaxError, error_str types = {} variables = {} functions = {} for i in xrange(0, parse.typeCount): - types[parse.types[i].name] = Type(core.BNNewTypeReference(parse.types[i].type)) + name = [] + for j in xrange(0, parse.types[i].nameCount): + name.append(parse.types[i].name[j]) + types[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.types[i].type)) for i in xrange(0, parse.variableCount): - variables[parse.variables[i].name] = Type(core.BNNewTypeReference(parse.variables[i].type)) + name = [] + for j in xrange(0, parse.variables[i].nameCount): + name.append(parse.variables[i].name[j]) + variables[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.variables[i].type)) for i in xrange(0, parse.functionCount): - functions[parse.functions[i].name] = Type(core.BNNewTypeReference(parse.functions[i].type)) - BNFreeTypeParserResult(parse) - return (TypeParserResult(types, variables, functions), error_str) + name = [] + for j in xrange(0, parse.functions[i].nameCount): + name.append(parse.functions[i].name[j]) + functions[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.functions[i].type)) + core.BNFreeTypeParserResult(parse) + return TypeParserResult(types, variables, functions) def register_calling_convention(self, cc): """ diff --git a/python/generator.cpp b/python/generator.cpp index 08485315..4c313fdd 100644 --- a/python/generator.cpp +++ b/python/generator.cpp @@ -97,11 +97,8 @@ void OutputType(FILE* out, Type* type, bool isReturnType = false, bool isCallbac else fprintf(out, "ctypes.c_double"); break; - case StructureTypeClass: - fprintf(out, "%s", type->GetQualifiedName(type->GetStructure()->GetName()).c_str()); - break; - case EnumerationTypeClass: - fprintf(out, "%s", type->GetQualifiedName(type->GetEnumeration()->GetName()).c_str()); + case NamedTypeReferenceClass: + fprintf(out, "%s", type->GetQualifiedName(type->GetNamedTypeReference()->GetName()).c_str()); break; case PointerTypeClass: if (isCallback || (type->GetChildType()->GetClass() == VoidTypeClass)) @@ -156,7 +153,7 @@ int main(int argc, char* argv[]) Architecture::Register(new GeneratorArchitecture()); // Parse API header to get type and function information - map> types, vars, funcs; + map, Ref> types, vars, funcs; string errors; bool ok = Architecture::GetByName("generator")->ParseTypesFromSourceFile(argv[1], types, vars, funcs, errors); fprintf(stderr, "%s", errors.c_str()); @@ -187,21 +184,25 @@ int main(int argc, char* argv[]) map enumMembers; for (auto& i : types) { + string name; + if (i.first.size() != 1) + continue; + name = i.first[0]; if (i.second->GetClass() == StructureTypeClass) { - fprintf(out, "class %s(ctypes.Structure):\n", i.first.c_str()); + fprintf(out, "class %s(ctypes.Structure):\n", name.c_str()); fprintf(out, " pass\n"); } else if (i.second->GetClass() == EnumerationTypeClass) { - fprintf(out, "%s = ctypes.c_int\n", i.first.c_str()); + fprintf(out, "%s = ctypes.c_int\n", name.c_str()); for (auto& j : i.second->GetEnumeration()->GetMembers()) fprintf(out, "%s = %" PRId64 "\n", j.name.c_str(), j.value); - fprintf(out, "%s_names = {\n", i.first.c_str()); + fprintf(out, "%s_names = {\n", name.c_str()); for (auto& j : i.second->GetEnumeration()->GetMembers()) fprintf(out, " %" PRId64 ": \"%s\",\n", j.value, j.name.c_str()); fprintf(out, "}\n"); - fprintf(out, "%s_by_name = {\n", i.first.c_str()); + fprintf(out, "%s_by_name = {\n", name.c_str()); for (auto& j : i.second->GetEnumeration()->GetMembers()) fprintf(out, " \"%s\": %" PRId64 ",\n", j.name.c_str(), j.value); fprintf(out, "}\n"); @@ -211,7 +212,7 @@ int main(int argc, char* argv[]) else if ((i.second->GetClass() == BoolTypeClass) || (i.second->GetClass() == IntegerTypeClass) || (i.second->GetClass() == FloatTypeClass) || (i.second->GetClass() == ArrayTypeClass)) { - fprintf(out, "%s = ", i.first.c_str()); + fprintf(out, "%s = ", name.c_str()); OutputType(out, i.second); fprintf(out, "\n"); } @@ -225,9 +226,13 @@ int main(int argc, char* argv[]) fprintf(out, "\n# Structure definitions\n"); for (auto& i : types) { + string name; + if (i.first.size() != 1) + continue; + name = i.first[0]; if ((i.second->GetClass() == StructureTypeClass) && (i.second->GetStructure()->GetMembers().size() != 0)) { - fprintf(out, "%s._fields_ = [\n", i.first.c_str()); + fprintf(out, "%s._fields_ = [\n", name.c_str()); for (auto& j : i.second->GetStructure()->GetMembers()) { fprintf(out, " (\"%s\", ", j.name.c_str()); @@ -241,6 +246,11 @@ int main(int argc, char* argv[]) fprintf(out, "\n# Function definitions\n"); for (auto& i : funcs) { + string name; + if (i.first.size() != 1) + continue; + name = i.first[0]; + // Check for a string result, these will be automatically wrapped to free the string // memory and return a Python string bool stringResult = (i.second->GetChildType()->GetClass() == PointerTypeClass) && @@ -249,7 +259,7 @@ int main(int argc, char* argv[]) // Pointer returns will be automatically wrapped to return None on null pointer bool pointerResult = (i.second->GetChildType()->GetClass() == PointerTypeClass); bool callbackConvention = false; - if (i.first == "BNAllocString") + if (name == "BNAllocString") { // Don't perform automatic wrapping of string allocation, and return a void // pointer so that callback functions (which is the only valid use of BNAllocString) @@ -258,11 +268,11 @@ int main(int argc, char* argv[]) callbackConvention = true; } - string funcName = i.first; + string funcName = name; if (stringResult || pointerResult) funcName = string("_") + funcName; - fprintf(out, "%s = core.%s\n", funcName.c_str(), i.first.c_str()); + fprintf(out, "%s = core.%s\n", funcName.c_str(), name.c_str()); fprintf(out, "%s.restype = ", funcName.c_str()); OutputType(out, i.second->GetChildType(), true, callbackConvention); fprintf(out, "\n"); @@ -272,7 +282,7 @@ int main(int argc, char* argv[]) for (auto& j : i.second->GetParameters()) { fprintf(out, " "); - if (i.first == "BNFreeString") + if (name == "BNFreeString") { // BNFreeString expects a pointer to a string allocated by the core, so do not use // a c_char_p here, as that would be allocated by the Python runtime. This can @@ -291,7 +301,7 @@ int main(int argc, char* argv[]) if (stringResult) { // Emit wrapper to get Python string and free native memory - fprintf(out, "def %s(*args):\n", i.first.c_str()); + fprintf(out, "def %s(*args):\n", name.c_str()); fprintf(out, " result = %s(*args)\n", funcName.c_str()); fprintf(out, " string = ctypes.cast(result, ctypes.c_char_p).value\n"); fprintf(out, " BNFreeString(result)\n"); @@ -300,7 +310,7 @@ int main(int argc, char* argv[]) else if (pointerResult) { // Emit wrapper to return None on null pointer - fprintf(out, "def %s(*args):\n", i.first.c_str()); + fprintf(out, "def %s(*args):\n", name.c_str()); fprintf(out, " result = %s(*args)\n", funcName.c_str()); fprintf(out, " if not result:\n"); fprintf(out, " return None\n"); diff --git a/type.cpp b/type.cpp index c8cfdc33..0571f743 100644 --- a/type.cpp +++ b/type.cpp @@ -133,6 +133,15 @@ Ref Type::GetEnumeration() const } +Ref Type::GetNamedTypeReference() const +{ + BNNamedTypeReference* ref = BNGetTypeNamedTypeReference(m_object); + if (ref) + return new NamedTypeReference(ref); + return nullptr; +} + + uint64_t Type::GetElementCount() const { return BNGetTypeElementCount(m_object); @@ -307,9 +316,21 @@ Ref Type::StructureType(Structure* strct) } -Ref Type::UnknownNamedType(UnknownType* unknwn) +Ref Type::NamedType(NamedTypeReference* ref, size_t width, size_t align) { - return new Type(BNCreateUnknownNamedType(unknwn->GetObject())); + return new Type(BNCreateNamedTypeReference(ref->GetObject(), width, align)); +} + + +Ref Type::NamedType(const vector& name, Type* type) +{ + const char** nameList = new const char*[name.size()]; + for (size_t i = 0; i < name.size(); i++) + nameList[i] = name[i].c_str(); + Type* result = new Type(BNCreateNamedTypeReferenceFromType(nameList, name.size(), + type ? type->GetObject() : nullptr)); + delete[] nameList; + return result; } @@ -355,35 +376,54 @@ void Type::SetFunctionCanReturn(bool canReturn) } -UnknownType::UnknownType(BNUnknownType* ut, vector names) +NamedTypeReference::NamedTypeReference(BNNamedTypeReference* nt) +{ + m_object = nt; +} + + +NamedTypeReference::NamedTypeReference(BNNamedTypeReferenceClass cls, const vector& names) { - m_object = ut; + m_object = BNCreateNamedType(); + BNSetTypeReferenceClass(m_object, cls); const char ** nameList = new const char*[names.size()]; for (size_t i = 0; i < names.size(); i++) { nameList[i] = names[i].c_str(); } - BNSetUnknownTypeName(ut, nameList, names.size()); + BNSetTypeReferenceName(m_object, nameList, names.size()); delete [] nameList; } -void UnknownType::SetName(const vector& names) +void NamedTypeReference::SetTypeClass(BNNamedTypeReferenceClass cls) +{ + BNSetTypeReferenceClass(m_object, cls); +} + + +BNNamedTypeReferenceClass NamedTypeReference::GetTypeClass() const +{ + return BNGetTypeReferenceClass(m_object); +} + + +void NamedTypeReference::SetName(const vector& names) { const char ** nameList = new const char*[names.size()]; for (size_t i = 0; i < names.size(); i++) { nameList[i] = names[i].c_str(); } - BNSetUnknownTypeName(m_object, nameList, names.size()); + BNSetTypeReferenceName(m_object, nameList, names.size()); delete [] nameList; } -vector UnknownType::GetName() const +vector NamedTypeReference::GetName() const { size_t size; - char** name = BNGetUnknownTypeName(m_object, &size); + char** name = BNGetTypeReferenceName(m_object, &size); vector result; for (size_t i = 0; i < size; i++) { @@ -407,33 +447,6 @@ Structure::Structure(BNStructure* s) } -vector Structure::GetName() const -{ - size_t size; - char** name = BNGetStructureName(m_object, &size); - vector result; - for (size_t i = 0; i < size; i++) - { - result.push_back(name[i]); - BNFreeString(name[i]); - } - delete [] name; - return result; -} - - -void Structure::SetName(const vector& names) -{ - const char ** nameList = new const char*[names.size()]; - for (size_t i = 0; i < names.size(); i++) - { - nameList[i] = names[i].c_str(); - } - BNSetStructureName(m_object, nameList, names.size()); - delete [] nameList; -} - - vector Structure::GetMembers() const { size_t count; @@ -532,32 +545,6 @@ Enumeration::Enumeration(BNEnumeration* e) } -vector Enumeration::GetName() const -{ - vector result; - size_t size; - char** name = BNGetEnumerationName(m_object, &size); - for (size_t i = 0; i < size; i++) - { - result.push_back(name[i]); - BNFreeString(name[i]); - } - delete [] name; - return result; -} - -void Enumeration::SetName(const vector& names) -{ - const char **const nameList = new const char*[names.size()]; - for (size_t i = 0; i < names.size(); i++) - { - nameList[i] = names[i].c_str(); - } - BNSetEnumerationName(m_object, nameList, names.size()); - delete [] nameList; -} - - vector Enumeration::GetMembers() const { size_t count; -- cgit v1.3.1 From 7e154a952fe5856b7cf650e2646ebc410b1fb506 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Wed, 11 Jan 2017 22:58:19 -0500 Subject: Add a qualified name object in the C API --- architecture.cpp | 24 ++------ binaryninjaapi.h | 8 ++- binaryninjacore.h | 34 ++++++----- binaryview.cpp | 72 ++++++++--------------- python/__init__.py | 166 ++++++++++++++++++++--------------------------------- type.cpp | 78 ++++++++++++++----------- 6 files changed, 161 insertions(+), 221 deletions(-) (limited to 'python/__init__.py') diff --git a/architecture.cpp b/architecture.cpp index 657d7bf0..0e25fa85 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -769,23 +769,17 @@ bool Architecture::ParseTypesFromSource(const string& source, const string& file for (size_t i = 0; i < result.typeCount; i++) { - QualifiedName name; - for (size_t j = 0; j < result.types[i].nameCount; j++) - name.push_back(result.types[i].name[j]); + QualifiedName name = QualifiedName::FromAPIObject(&result.types[i].name); types[name] = new Type(BNNewTypeReference(result.types[i].type)); } for (size_t i = 0; i < result.variableCount; i++) { - QualifiedName name; - for (size_t j = 0; j < result.variables[i].nameCount; j++) - name.push_back(result.variables[i].name[j]); + QualifiedName name = QualifiedName::FromAPIObject(&result.variables[i].name); types[name] = new Type(BNNewTypeReference(result.variables[i].type)); } for (size_t i = 0; i < result.functionCount; i++) { - QualifiedName name; - for (size_t j = 0; j < result.functions[i].nameCount; j++) - name.push_back(result.functions[i].name[j]); + QualifiedName name = QualifiedName::FromAPIObject(&result.functions[i].name); types[name] = new Type(BNNewTypeReference(result.functions[i].type)); } BNFreeTypeParserResult(&result); @@ -817,23 +811,17 @@ bool Architecture::ParseTypesFromSourceFile(const string& fileName, map view = new BinaryView(BNNewViewReference(data)); Ref typeObj = new Type(BNNewTypeReference(type)); - QualifiedName nameList; - for (size_t i = 0; i < nameCount; i++) - nameList.push_back(name[i]); - notify->OnTypeDefined(view, nameList, typeObj); + notify->OnTypeDefined(view, QualifiedName::FromAPIObject(name), typeObj); } -void BinaryDataNotification::TypeUndefinedCallback(void* ctxt, BNBinaryView* data, const char** name, size_t nameCount, - BNType* type) +void BinaryDataNotification::TypeUndefinedCallback(void* ctxt, BNBinaryView* data, BNQualifiedName* name, BNType* type) { BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; Ref view = new BinaryView(BNNewViewReference(data)); Ref typeObj = new Type(BNNewTypeReference(type)); - QualifiedName nameList; - for (size_t i = 0; i < nameCount; i++) - nameList.push_back(name[i]); - notify->OnTypeUndefined(view, nameList, typeObj); + notify->OnTypeUndefined(view, QualifiedName::FromAPIObject(name), typeObj); } @@ -1467,8 +1459,7 @@ bool BinaryView::ParseTypeString(const string& text, QualifiedNameAndType& resul return false; } - for (size_t i = 0; i < nt.nameCount; i++) - result.name.push_back(nt.name[i]); + result.name = QualifiedName::FromAPIObject(&nt.name); result.type = new Type(BNNewTypeReference(nt.type)); errors = ""; BNFreeQualifiedNameAndType(&nt); @@ -1484,9 +1475,7 @@ map> BinaryView::GetTypes() map> result; for (size_t i = 0; i < count; i++) { - QualifiedName name; - for (size_t j = 0; j < types[i].nameCount; j++) - name.push_back(types[i].name[j]); + QualifiedName name = QualifiedName::FromAPIObject(&types[i].name); result[name] = new Type(BNNewTypeReference(types[i].type)); } @@ -1497,12 +1486,9 @@ map> BinaryView::GetTypes() Ref BinaryView::GetTypeByName(const QualifiedName& name) { - const char** nameList = new const char*[name.size()]; - for (size_t i = 0; i < name.size(); i++) - nameList[i] = name[i].c_str(); - - BNType* type = BNGetAnalysisTypeByName(m_object, nameList, name.size()); - delete[] nameList; + BNQualifiedName nameObj = name.GetAPIObject(); + BNType* type = BNGetAnalysisTypeByName(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); if (!type) return nullptr; @@ -1512,52 +1498,42 @@ Ref BinaryView::GetTypeByName(const QualifiedName& name) bool BinaryView::IsTypeAutoDefined(const QualifiedName& name) { - const char** nameList = new const char*[name.size()]; - for (size_t i = 0; i < name.size(); i++) - nameList[i] = name[i].c_str(); - bool result = BNIsAnalysisTypeAutoDefined(m_object, nameList, name.size()); - delete[] nameList; + BNQualifiedName nameObj = name.GetAPIObject(); + bool result = BNIsAnalysisTypeAutoDefined(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); return result; } void BinaryView::DefineType(const QualifiedName& name, Ref type) { - const char** nameList = new const char*[name.size()]; - for (size_t i = 0; i < name.size(); i++) - nameList[i] = name[i].c_str(); - BNDefineAnalysisType(m_object, nameList, name.size(), type->GetObject()); - delete[] nameList; + BNQualifiedName nameObj = name.GetAPIObject(); + BNDefineAnalysisType(m_object, &nameObj, type->GetObject()); + QualifiedName::FreeAPIObject(&nameObj); } void BinaryView::DefineUserType(const QualifiedName& name, Ref type) { - const char** nameList = new const char*[name.size()]; - for (size_t i = 0; i < name.size(); i++) - nameList[i] = name[i].c_str(); - BNDefineUserAnalysisType(m_object, nameList, name.size(), type->GetObject()); - delete[] nameList; + BNQualifiedName nameObj = name.GetAPIObject(); + BNDefineUserAnalysisType(m_object, &nameObj, type->GetObject()); + QualifiedName::FreeAPIObject(&nameObj); } void BinaryView::UndefineType(const QualifiedName& name) { - const char** nameList = new const char*[name.size()]; - for (size_t i = 0; i < name.size(); i++) - nameList[i] = name[i].c_str(); - BNUndefineAnalysisType(m_object, nameList, name.size()); - delete[] nameList; + BNQualifiedName nameObj = name.GetAPIObject(); + BNUndefineAnalysisType(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); } void BinaryView::UndefineUserType(const QualifiedName& name) { - const char** nameList = new const char*[name.size()]; - for (size_t i = 0; i < name.size(); i++) - nameList[i] = name[i].c_str(); - BNUndefineUserAnalysisType(m_object, nameList, name.size()); - delete[] nameList; + BNQualifiedName nameObj = name.GetAPIObject(); + BNUndefineUserAnalysisType(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); } diff --git a/python/__init__.py b/python/__init__.py index b5ced583..c2db468d 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -664,6 +664,8 @@ class QualifiedName(object): def __init__(self, name = []): if isinstance(name, str): self.name = [name] + elif isinstance(name, QualifiedName): + self.name = name.name else: self.name = name @@ -724,6 +726,22 @@ class QualifiedName(object): def __iter__(self): return iter(self.name) + def _get_core_struct(self): + result = core.BNQualifiedName() + name_list = (ctypes.c_char_p * len(self.name))() + for i in xrange(0, len(self.name)): + name_list[i] = self.name[i] + result.name = name_list + result.nameCount = len(self.name) + return result + + @classmethod + def _from_core_struct(cls, name): + result = [] + for i in xrange(0, name.nameCount): + result.append(name.name[i]) + return QualifiedName(result) + class BinaryDataNotificationCallbacks(object): def __init__(self, view, notify): self.view = view @@ -825,21 +843,17 @@ class BinaryDataNotificationCallbacks(object): except: log_error(traceback.format_exc()) - def _type_defined(self, ctxt, name, name_count, type_obj): + def _type_defined(self, ctxt, name, type_obj): try: - name_list = [] - for i in xrange(0, name_count): - name_list.append(name[i]) - self.notify.type_defined(self.view, QualifiedName(name_list), Type(core.BNNewTypeReference(type_obj))) + qualified_name = QualifiedName._from_core_struct(name[0]) + self.notify.type_defined(self.view, qualified_name, Type(core.BNNewTypeReference(type_obj))) except: log_error(traceback.format_exc()) - def _type_undefined(self, ctxt, name, name_count, type_obj): + def _type_undefined(self, ctxt, name, type_obj): try: - name_list = [] - for i in xrange(0, name_count): - name_list.append(name[i]) - self.notify.type_undefined(self.view, QualifiedName(name_list), Type(core.BNNewTypeReference(type_obj))) + qualified_name = QualifiedName._from_core_struct(name[0]) + self.notify.type_undefined(self.view, qualified_name, Type(core.BNNewTypeReference(type_obj))) except: log_error(traceback.format_exc()) @@ -1464,10 +1478,8 @@ class BinaryView(object): type_list = core.BNGetAnalysisTypeList(self.handle, count) result = {} for i in xrange(0, count.value): - name = [] - for j in xrange(0, type_list[i].nameCount): - name.append(type_list[i].name[j]) - result[QualifiedName(name)] = Type(core.BNNewTypeReference(type_list[i].type)) + name = QualifiedName._from_core_struct(type_list[i].name) + result[name] = Type(core.BNNewTypeReference(type_list[i].type)) core.BNFreeTypeList(type_list, count.value) return result @@ -3438,10 +3450,7 @@ class BinaryView(object): core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) raise SyntaxError, error_str type_obj = Type(core.BNNewTypeReference(result.type)) - name = [] - for i in xrange(0, result.nameCount): - name.append(result.name[i]) - name = QualifiedName(name) + name = QualifiedName._from_core_struct(result.name) core.BNFreeQualifiedNameAndType(result) return type_obj, name @@ -3460,12 +3469,8 @@ class BinaryView(object): >>> """ - if isinstance(name, str): - name = [name] - name_list = (ctypes.c_char_p * len(name))() - for i in xrange(0, len(name)): - name_list[i] = name[i] - obj = core.BNGetAnalysisTypeByName(self.handle, name_list, len(name)) + name = QualifiedName(name)._get_core_struct() + obj = core.BNGetAnalysisTypeByName(self.handle, name) if not obj: return None return Type(obj) @@ -3485,12 +3490,8 @@ class BinaryView(object): False >>> """ - if isinstance(name, str): - name = [name] - name_list = (ctypes.c_char_p * len(name))() - for i in xrange(0, len(name)): - name_list[i] = name[i] - return core.BNIsAnalysisTypeAutoDefined(self.handle, name_list, len(name)) + name = QualifiedName(name)._get_core_struct() + return core.BNIsAnalysisTypeAutoDefined(self.handle, name) def define_type(self, name, type_obj): """ @@ -3507,12 +3508,8 @@ class BinaryView(object): >>> bv.get_type_by_name(name) """ - if isinstance(name, str): - name = [name] - name_list = (ctypes.c_char_p * len(name))() - for i in xrange(0, len(name)): - name_list[i] = name[i] - core.BNDefineAnalysisType(self.handle, name_list, len(name), type_obj.handle) + name = QualifiedName(name)._get_core_struct() + core.BNDefineAnalysisType(self.handle, name, type_obj.handle) def define_user_type(self, name, type_obj): """ @@ -3529,12 +3526,8 @@ class BinaryView(object): >>> bv.get_type_by_name(name) """ - if isinstance(name, str): - name = [name] - name_list = (ctypes.c_char_p * len(name))() - for i in xrange(0, len(name)): - name_list[i] = name[i] - core.BNDefineUserAnalysisType(self.handle, name_list, len(name), type_obj.handle) + name = QualifiedName(name)._get_core_struct() + core.BNDefineUserAnalysisType(self.handle, name, type_obj.handle) def undefine_type(self, name): """ @@ -3552,12 +3545,8 @@ class BinaryView(object): >>> bv.get_type_by_name(name) >>> """ - if isinstance(name, str): - name = [name] - name_list = (ctypes.c_char_p * len(name))() - for i in xrange(0, len(name)): - name_list[i] = name[i] - core.BNUndefineAnalysisType(self.handle, name_list, len(name)) + name = QualifiedName(name)._get_core_struct() + core.BNUndefineAnalysisType(self.handle, name) def undefine_user_type(self, name): """ @@ -3576,12 +3565,8 @@ class BinaryView(object): >>> bv.get_type_by_name(name) >>> """ - if isinstance(name, str): - name = [name] - name_list = (ctypes.c_char_p * len(name))() - for i in xrange(0, len(name)): - name_list[i] = name[i] - core.BNUndefineUserAnalysisType(self.handle, name_list, len(name)) + name = QualifiedName(name)._get_core_struct() + core.BNUndefineUserAnalysisType(self.handle, name) def find_next_data(self, start, data, flags = 0): """ @@ -4470,14 +4455,10 @@ class Type(object): @classmethod def named_type_from_type(self, name, t): - if isinstance(name, str): - name = [name] - name_list = (ctypes.c_char_p * len(name))() - for i in xrange(0, len(name)): - name_list[i] = name[i] + name = QualifiedName(name)._get_core_struct() if t is not None: t = t.handle - return Type(core.BNCreateNamedTypeReferenceFromType(name_list, len(name), t)) + return Type(core.BNCreateNamedTypeReferenceFromType(name, t)) @classmethod def enumeration_type(self, arch, e, width = None): @@ -4521,12 +4502,8 @@ class NamedTypeReference(object): self.handle = core.BNCreateNamedType() core.BNSetTypeReferenceClass(self.handle, type_class) if name is not None: - if isinstance(name, str): - name = [name] - name_list = (ctypes.c_char_p * len(name))() - for i in xrange(0, len(name)): - name_list[i] = name[i] - core.BNSetTypeReferenceName(self.handle, name_list, len(name)) + name = QualifiedName(name)._get_core_struct() + core.BNSetTypeReferenceName(self.handle, name) else: self.handle = handle @@ -4544,20 +4521,15 @@ class NamedTypeReference(object): @property def name(self): count = ctypes.c_ulonglong() - nameList = core.BNGetTypeReferenceName(self.handle, count) - result = [] - for i in xrange(count.value): - result.append(nameList[i]) - return QualifiedName(result) + name = core.BNGetTypeReferenceName(self.handle, count) + result = QualifiedName._from_core_struct(name) + core.BNFreeQualifiedName(name) + return result @name.setter def name(self, value): - if isinstance(value, str): - value = [value] - name_list = (ctypes.c_char_p * len(value))() - for i in xrange(0, len(value)): - name_list[i] = value[i] - core.BNSetTypeReferenceName(self.handle, name_list, len(value)) + value = QualifiedName(value)._get_core_struct() + core.BNSetTypeReferenceName(self.handle, value) def __repr__(self): if self.type_class == core.TypedefNamedTypeClass: @@ -4646,8 +4618,6 @@ class Structure(object): raise AttributeError, "attribute '%s' is read only" % name def __repr__(self): - if len(self.name) > 0: - return "" % self.name return "" % self.width def append(self, t, name = ""): @@ -4696,8 +4666,6 @@ class Enumeration(object): raise AttributeError, "attribute '%s' is read only" % name def __repr__(self): - if len(self.name) > 0: - return "" % self.name return "" % repr(self.members) def append(self, name, value = None): @@ -7581,20 +7549,14 @@ class Architecture(object): variables = {} functions = {} for i in xrange(0, parse.typeCount): - name = [] - for j in xrange(0, parse.types[i].nameCount): - name.append(parse.types[i].name[j]) - types[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.types[i].type)) + name = QualifiedName._from_core_struct(parse.types[i].name) + types[name] = Type(core.BNNewTypeReference(parse.types[i].type)) for i in xrange(0, parse.variableCount): - name = [] - for j in xrange(0, parse.variables[i].nameCount): - name.append(parse.variables[i].name[j]) - variables[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.variables[i].type)) + name = QualifiedName._from_core_struct(parse.variables[i].name) + variables[name] = Type(core.BNNewTypeReference(parse.variables[i].type)) for i in xrange(0, parse.functionCount): - name = [] - for j in xrange(0, parse.functions[i].nameCount): - name.append(parse.functions[i].name[j]) - functions[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.functions[i].type)) + name = QualifiedName._from_core_struct(parse.functions[i].name) + functions[name] = Type(core.BNNewTypeReference(parse.functions[i].type)) core.BNFreeTypeParserResult(parse) return TypeParserResult(types, variables, functions) @@ -7631,20 +7593,14 @@ class Architecture(object): variables = {} functions = {} for i in xrange(0, parse.typeCount): - name = [] - for j in xrange(0, parse.types[i].nameCount): - name.append(parse.types[i].name[j]) - types[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.types[i].type)) + name = QualifiedName._from_core_struct(parse.types[i].name) + types[name] = Type(core.BNNewTypeReference(parse.types[i].type)) for i in xrange(0, parse.variableCount): - name = [] - for j in xrange(0, parse.variables[i].nameCount): - name.append(parse.variables[i].name[j]) - variables[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.variables[i].type)) + name = QualifiedName._from_core_struct(parse.variables[i].name) + variables[name] = Type(core.BNNewTypeReference(parse.variables[i].type)) for i in xrange(0, parse.functionCount): - name = [] - for j in xrange(0, parse.functions[i].nameCount): - name.append(parse.functions[i].name[j]) - functions[QualifiedName(name)] = Type(core.BNNewTypeReference(parse.functions[i].type)) + name = QualifiedName._from_core_struct(parse.functions[i].name) + functions[name] = Type(core.BNNewTypeReference(parse.functions[i].type)) core.BNFreeTypeParserResult(parse) return TypeParserResult(types, variables, functions) diff --git a/type.cpp b/type.cpp index ae8f04d3..e71077e6 100644 --- a/type.cpp +++ b/type.cpp @@ -209,6 +209,34 @@ string QualifiedName::GetString() const } +BNQualifiedName QualifiedName::GetAPIObject() const +{ + BNQualifiedName result; + result.nameCount = m_name.size(); + result.name = new char*[m_name.size()]; + for (size_t i = 0; i < m_name.size(); i++) + result.name[i] = BNAllocString(m_name[i].c_str()); + return result; +} + + +void QualifiedName::FreeAPIObject(BNQualifiedName* name) +{ + for (size_t i = 0; i < name->nameCount; i++) + BNFreeString(name->name[i]); + delete[] name->name; +} + + +QualifiedName QualifiedName::FromAPIObject(BNQualifiedName* name) +{ + QualifiedName result; + for (size_t i = 0; i < name->nameCount; i++) + result.push_back(name->name[i]); + return result; +} + + Type::Type(BNType* type) { m_object = type; @@ -344,13 +372,9 @@ string Type::GetString() const string Type::GetTypeAndName(const QualifiedName& nameList) const { - const char ** str = new const char*[nameList.size()]; - for (size_t i = 0; i < nameList.size(); i++) - { - str[i] = nameList[i].c_str(); - } - char* outName = BNGetTypeAndName(m_object, str, nameList.size()); - delete [] str; + BNQualifiedName name = nameList.GetAPIObject(); + char* outName = BNGetTypeAndName(m_object, &name); + QualifiedName::FreeAPIObject(&name); return outName; } @@ -488,12 +512,9 @@ Ref Type::NamedType(NamedTypeReference* ref, size_t width, size_t align) Ref Type::NamedType(const QualifiedName& name, Type* type) { - const char** nameList = new const char*[name.size()]; - for (size_t i = 0; i < name.size(); i++) - nameList[i] = name[i].c_str(); - Type* result = new Type(BNCreateNamedTypeReferenceFromType(nameList, name.size(), - type ? type->GetObject() : nullptr)); - delete[] nameList; + BNQualifiedName nameObj = name.GetAPIObject(); + Type* result = new Type(BNCreateNamedTypeReferenceFromType(&nameObj, type ? type->GetObject() : nullptr)); + QualifiedName::FreeAPIObject(&nameObj); return result; } @@ -550,13 +571,12 @@ NamedTypeReference::NamedTypeReference(BNNamedTypeReferenceClass cls, const Qual { m_object = BNCreateNamedType(); BNSetTypeReferenceClass(m_object, cls); - const char ** nameList = new const char*[names.size()]; - for (size_t i = 0; i < names.size(); i++) + if (names.size() != 0) { - nameList[i] = names[i].c_str(); + BNQualifiedName nameObj = names.GetAPIObject(); + BNSetTypeReferenceName(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); } - BNSetTypeReferenceName(m_object, nameList, names.size()); - delete [] nameList; } @@ -574,27 +594,17 @@ BNNamedTypeReferenceClass NamedTypeReference::GetTypeClass() const void NamedTypeReference::SetName(const QualifiedName& names) { - const char ** nameList = new const char*[names.size()]; - for (size_t i = 0; i < names.size(); i++) - { - nameList[i] = names[i].c_str(); - } - BNSetTypeReferenceName(m_object, nameList, names.size()); - delete [] nameList; + BNQualifiedName nameObj = names.GetAPIObject(); + BNSetTypeReferenceName(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); } QualifiedName NamedTypeReference::GetName() const { - size_t size; - char** name = BNGetTypeReferenceName(m_object, &size); - QualifiedName result; - for (size_t i = 0; i < size; i++) - { - result.push_back(name[i]); - BNFreeString(name[i]); - } - delete [] name; + BNQualifiedName name = BNGetTypeReferenceName(m_object); + QualifiedName result = QualifiedName::FromAPIObject(&name); + BNFreeQualifiedName(&name); return result; } -- cgit v1.3.1 From 8df9a34dd67c852626432c84a5007be3173c33e0 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 6 Feb 2017 22:27:42 -0500 Subject: Add type IDs for types to track across renames --- binaryninjaapi.cpp | 9 ++++ binaryninjaapi.h | 27 +++++++++-- binaryninjacore.h | 19 ++++++-- binaryview.cpp | 54 +++++++++++++++++++--- python/__init__.py | 4 ++ python/binaryview.py | 126 ++++++++++++++++++++++++++++++++++++++++++++------- python/types.py | 63 +++++++++++++++++++++++--- type.cpp | 90 +++++++++++++++++++++++++++++++++++- 8 files changed, 354 insertions(+), 38 deletions(-) (limited to 'python/__init__.py') diff --git a/binaryninjaapi.cpp b/binaryninjaapi.cpp index e1dab528..099f35eb 100644 --- a/binaryninjaapi.cpp +++ b/binaryninjaapi.cpp @@ -237,3 +237,12 @@ void BinaryNinja::SetWorkerThreadCount(size_t count) { BNSetWorkerThreadCount(count); } + + +string BinaryNinja::GetUniqueIdentifierString() +{ + char* str = BNGetUniqueIdentifierString(); + string result = str; + BNFreeString(str); + return result; +} diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 4e3f3d57..92eeba30 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -409,6 +409,8 @@ namespace BinaryNinja BNMessageBoxButtonResult ShowMessageBox(const std::string& title, const std::string& text, BNMessageBoxButtonSet buttons = OKButtonSet, BNMessageBoxIcon icon = InformationIcon); + std::string GetUniqueIdentifierString(); + class QualifiedName { std::vector m_name; @@ -1027,11 +1029,15 @@ namespace BinaryNinja std::map> GetTypes(); Ref GetTypeByName(const QualifiedName& name); + Ref GetTypeById(const std::string& id); + std::string GetTypeId(const QualifiedName& name); + QualifiedName GetTypeNameById(const std::string& id); bool IsTypeAutoDefined(const QualifiedName& name); - void DefineType(const QualifiedName& name, Ref type); + QualifiedName DefineType(const std::string& id, const QualifiedName& defaultName, Ref type); void DefineUserType(const QualifiedName& name, Ref type); - void UndefineType(const QualifiedName& name); + void UndefineType(const std::string& id); void UndefineUserType(const QualifiedName& name); + void RenameType(const QualifiedName& oldName, const QualifiedName& newName); bool FindNextData(uint64_t start, const DataBuffer& data, uint64_t& result, BNFindFlag flags = NoFindFlags); @@ -1611,12 +1617,18 @@ namespace BinaryNinja static Ref StructureType(Structure* strct); static Ref NamedType(NamedTypeReference* ref, size_t width = 0, size_t align = 1); static Ref NamedType(const QualifiedName& name, Type* type); + static Ref NamedType(const std::string& id, const QualifiedName& name, Type* type); + static Ref NamedType(BinaryView* view, const QualifiedName& name); static Ref EnumerationType(Architecture* arch, Enumeration* enm, size_t width = 0, bool issigned = false); static Ref PointerType(Architecture* arch, Type* type, bool cnst = false, bool vltl = false, BNReferenceType refType = PointerReferenceType); static Ref ArrayType(Type* type, uint64_t elem); static Ref FunctionType(Type* returnValue, CallingConvention* callingConvention, const std::vector& params, bool varArg = false); + + static std::string GenerateAutoTypeId(const std::string& source, const QualifiedName& name); + static std::string GenerateAutoPlatformTypeId(const QualifiedName& name); + static std::string GenerateAutoDemangledTypeId(const QualifiedName& name); }; class NamedTypeReference: public CoreRefCountObject GenerateAutoTypeReference(BNNamedTypeReferenceClass cls, + const std::string& source, const QualifiedName& name); + static Ref GenerateAutoPlatformTypeReference(BNNamedTypeReferenceClass cls, + const QualifiedName& name); + static Ref GenerateAutoDemangledTypeReference(BNNamedTypeReferenceClass cls, + const QualifiedName& name); }; struct StructureMember diff --git a/binaryninjacore.h b/binaryninjacore.h index 7d3bc14c..b454da64 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1234,6 +1234,8 @@ extern "C" BINARYNINJACOREAPI void BNRegisterObjectDestructionCallbacks(BNObjectDestructionCallbacks* callbacks); BINARYNINJACOREAPI void BNUnregisterObjectDestructionCallbacks(BNObjectDestructionCallbacks* callbacks); + BINARYNINJACOREAPI char* BNGetUniqueIdentifierString(void); + // Plugin initialization BINARYNINJACOREAPI void BNInitCorePlugins(void); BINARYNINJACOREAPI void BNInitUserPlugins(void); @@ -1807,11 +1809,19 @@ extern "C" BINARYNINJACOREAPI BNQualifiedNameAndType* BNGetAnalysisTypeList(BNBinaryView* view, size_t* count); BINARYNINJACOREAPI void BNFreeTypeList(BNQualifiedNameAndType* types, size_t count); BINARYNINJACOREAPI BNType* BNGetAnalysisTypeByName(BNBinaryView* view, BNQualifiedName* name); + BINARYNINJACOREAPI BNType* BNGetAnalysisTypeById(BNBinaryView* view, const char* id); + BINARYNINJACOREAPI char* BNGetAnalysisTypeId(BNBinaryView* view, BNQualifiedName* name); + BINARYNINJACOREAPI BNQualifiedName BNGetAnalysisTypeNameById(BNBinaryView* view, const char* id); BINARYNINJACOREAPI bool BNIsAnalysisTypeAutoDefined(BNBinaryView* view, BNQualifiedName* name); - BINARYNINJACOREAPI void BNDefineAnalysisType(BNBinaryView* view, BNQualifiedName* name, BNType* type); + BINARYNINJACOREAPI BNQualifiedName BNDefineAnalysisType(BNBinaryView* view, const char* id, + BNQualifiedName* defaultName, BNType* type); BINARYNINJACOREAPI void BNDefineUserAnalysisType(BNBinaryView* view, BNQualifiedName* name, BNType* type); - BINARYNINJACOREAPI void BNUndefineAnalysisType(BNBinaryView* view, BNQualifiedName* name); + BINARYNINJACOREAPI void BNUndefineAnalysisType(BNBinaryView* view, const char* id); BINARYNINJACOREAPI void BNUndefineUserAnalysisType(BNBinaryView* view, BNQualifiedName* name); + BINARYNINJACOREAPI void BNRenameAnalysisType(BNBinaryView* view, BNQualifiedName* oldName, BNQualifiedName* newName); + BINARYNINJACOREAPI char* BNGenerateAutoTypeId(const char* source, BNQualifiedName* name); + BINARYNINJACOREAPI char* BNGenerateAutoPlatformTypeId(BNQualifiedName* name); + BINARYNINJACOREAPI char* BNGenerateAutoDemangledTypeId(BNQualifiedName* name); BINARYNINJACOREAPI void BNReanalyzeAllFunctions(BNBinaryView* view); BINARYNINJACOREAPI void BNReanalyzeFunction(BNFunction* func); @@ -2006,10 +2016,13 @@ extern "C" BINARYNINJACOREAPI void BNFreeTokenList(BNInstructionTextToken* tokens, size_t count); BINARYNINJACOREAPI BNType* BNCreateNamedTypeReference(BNNamedTypeReference* nt, size_t width, size_t align); - BINARYNINJACOREAPI BNType* BNCreateNamedTypeReferenceFromType(BNQualifiedName* name, BNType* type); + BINARYNINJACOREAPI BNType* BNCreateNamedTypeReferenceFromTypeAndId(const char* id, BNQualifiedName* name, BNType* type); + BINARYNINJACOREAPI BNType* BNCreateNamedTypeReferenceFromType(BNBinaryView* view, BNQualifiedName* name); BINARYNINJACOREAPI BNNamedTypeReference* BNCreateNamedType(void); BINARYNINJACOREAPI void BNSetTypeReferenceClass(BNNamedTypeReference* nt, BNNamedTypeReferenceClass cls); BINARYNINJACOREAPI BNNamedTypeReferenceClass BNGetTypeReferenceClass(BNNamedTypeReference* nt); + BINARYNINJACOREAPI void BNSetTypeReferenceId(BNNamedTypeReference* nt, const char* id); + BINARYNINJACOREAPI char* BNGetTypeReferenceId(BNNamedTypeReference* nt); BINARYNINJACOREAPI void BNSetTypeReferenceName(BNNamedTypeReference* nt, BNQualifiedName* name); BINARYNINJACOREAPI BNQualifiedName BNGetTypeReferenceName(BNNamedTypeReference* nt); BINARYNINJACOREAPI void BNFreeQualifiedName(BNQualifiedName* name); diff --git a/binaryview.cpp b/binaryview.cpp index cc8bb733..1b1574e1 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1496,6 +1496,35 @@ Ref BinaryView::GetTypeByName(const QualifiedName& name) } +Ref BinaryView::GetTypeById(const string& id) +{ + BNType* type = BNGetAnalysisTypeById(m_object, id.c_str()); + if (!type) + return nullptr; + return new Type(type); +} + + +QualifiedName BinaryView::GetTypeNameById(const string& id) +{ + BNQualifiedName name = BNGetAnalysisTypeNameById(m_object, id.c_str()); + QualifiedName result = QualifiedName::FromAPIObject(&name); + BNFreeQualifiedName(&name); + return result; +} + + +string BinaryView::GetTypeId(const QualifiedName& name) +{ + BNQualifiedName nameObj = name.GetAPIObject(); + char* id = BNGetAnalysisTypeId(m_object, &nameObj); + QualifiedName::FreeAPIObject(&nameObj); + string result = id; + BNFreeString(id); + return result; +} + + bool BinaryView::IsTypeAutoDefined(const QualifiedName& name) { BNQualifiedName nameObj = name.GetAPIObject(); @@ -1505,11 +1534,14 @@ bool BinaryView::IsTypeAutoDefined(const QualifiedName& name) } -void BinaryView::DefineType(const QualifiedName& name, Ref type) +QualifiedName BinaryView::DefineType(const string& id, const QualifiedName& defaultName, Ref type) { - BNQualifiedName nameObj = name.GetAPIObject(); - BNDefineAnalysisType(m_object, &nameObj, type->GetObject()); + BNQualifiedName nameObj = defaultName.GetAPIObject(); + BNQualifiedName regName = BNDefineAnalysisType(m_object, id.c_str(), &nameObj, type->GetObject()); QualifiedName::FreeAPIObject(&nameObj); + QualifiedName result = QualifiedName::FromAPIObject(®Name); + BNFreeQualifiedName(®Name); + return result; } @@ -1521,11 +1553,9 @@ void BinaryView::DefineUserType(const QualifiedName& name, Ref type) } -void BinaryView::UndefineType(const QualifiedName& name) +void BinaryView::UndefineType(const string& id) { - BNQualifiedName nameObj = name.GetAPIObject(); - BNUndefineAnalysisType(m_object, &nameObj); - QualifiedName::FreeAPIObject(&nameObj); + BNUndefineAnalysisType(m_object, id.c_str()); } @@ -1537,6 +1567,16 @@ void BinaryView::UndefineUserType(const QualifiedName& name) } +void BinaryView::RenameType(const QualifiedName& oldName, const QualifiedName& newName) +{ + BNQualifiedName oldNameObj = oldName.GetAPIObject(); + BNQualifiedName newNameObj = newName.GetAPIObject(); + BNRenameAnalysisType(m_object, &oldNameObj, &newNameObj); + QualifiedName::FreeAPIObject(&oldNameObj); + QualifiedName::FreeAPIObject(&newNameObj); +} + + bool BinaryView::FindNextData(uint64_t start, const DataBuffer& data, uint64_t& result, BNFindFlag flags) { return BNFindNextData(m_object, start, data.GetBufferObject(), &result, flags); diff --git a/python/__init__.py b/python/__init__.py index a1ea02f5..9b87aa47 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -51,6 +51,10 @@ def shutdown(): core.BNShutdown() +def get_unique_identifier(): + return core.BNGetUniqueIdentifierString() + + class _DestructionCallbackHandler(object): def __init__(self): self._cb = core.BNObjectDestructionCallbacks() diff --git a/python/binaryview.py b/python/binaryview.py index ba706fe5..2cdacb4c 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -2881,7 +2881,7 @@ class BinaryView(object): :Example: >>> type, name = bv.parse_type_string("int foo") - >>> bv.define_type(name, type) + >>> bv.define_user_type(name, type) >>> bv.get_type_by_name(name) >>> @@ -2892,6 +2892,71 @@ class BinaryView(object): return None return types.Type(obj) + def get_type_by_id(self, id): + """ + ``get_type_by_id`` returns the defined type whose unique identifier corresponds with the provided ``id`` + + :param str id: Unique identifier to lookup + :return: A :py:Class:`Type` or None if the type does not exist + :rtype: Type or None + :Example: + + >>> type, name = bv.parse_type_string("int foo") + >>> type_id = Type.generate_auto_type_id("source", name) + >>> bv.define_type(type_id, name, type) + >>> bv.get_type_by_id(type_id) + + >>> + """ + obj = core.BNGetAnalysisTypeById(self.handle, id) + if not obj: + return None + return types.Type(obj) + + def get_type_name_by_id(self, id): + """ + ``get_type_name_by_id`` returns the defined type name whose unique identifier corresponds with the provided ``id`` + + :param str id: Unique identifier to lookup + :return: A QualifiedName or None if the type does not exist + :rtype: QualifiedName or None + :Example: + + >>> type, name = bv.parse_type_string("int foo") + >>> type_id = Type.generate_auto_type_id("source", name) + >>> bv.define_type(type_id, name, type) + 'foo' + >>> bv.get_type_name_by_id(type_id) + 'foo' + >>> + """ + name = core.BNGetAnalysisTypeNameById(self.handle, id) + result = types.QualifiedName._from_core_struct(name) + core.BNFreeQualifiedName(name) + if len(result) == 0: + return None + return result + + def get_type_id(self, name): + """ + ``get_type_id`` returns the unique indentifier of the defined type whose name corresponds with the + provided ``name`` + + :param QualifiedName name: Type name to lookup + :return: The unique identifier of the type + :rtype: str + :Example: + + >>> type, name = bv.parse_type_string("int foo") + >>> type_id = Type.generate_auto_type_id("source", name) + >>> registered_name = bv.define_type(type_id, name, type) + >>> bv.get_type_id(registered_name) == type_id + True + >>> + """ + name = types.QualifiedName(name)._get_core_struct() + return core.BNGetAnalysisTypeId(self.handle, name) + def is_type_auto_defined(self, name): """ ``is_type_auto_defined`` queries the user type list of name. If name is not in the *user* type list then the name @@ -2910,23 +2975,28 @@ class BinaryView(object): name = types.QualifiedName(name)._get_core_struct() return core.BNIsAnalysisTypeAutoDefined(self.handle, name) - def define_type(self, name, type_obj): + def define_type(self, type_id, default_name, type_obj): """ ``define_type`` registers a :py:Class:`Type` ``type_obj`` of the given ``name`` in the global list of types for - the current :py:Class:`BinaryView`. + the current :py:Class:`BinaryView`. This method should only be used for automatically generated types. - :param QualifiedName name: Name of the type to be registered + :param str type_id: Unique identifier for the automatically generated type + :param QualifiedName default_name: Name of the type to be registered :param Type type_obj: Type object to be registered - :rtype: None + :return: Registered name of the type. May not be the same as the requested name if the user has renamed types. + :rtype: QualifiedName :Example: >>> type, name = bv.parse_type_string("int foo") - >>> bv.define_type(name, type) - >>> bv.get_type_by_name(name) + >>> registered_name = bv.define_type(Type.generate_auto_type_id("source", name), name, type) + >>> bv.get_type_by_name(registered_name) """ - name = types.QualifiedName(name)._get_core_struct() - core.BNDefineAnalysisType(self.handle, name, type_obj.handle) + name = types.QualifiedName(default_name)._get_core_struct() + reg_name = core.BNDefineAnalysisType(self.handle, type_id, name, type_obj.handle) + result = types.QualifiedName._from_core_struct(reg_name) + core.BNFreeQualifiedName(reg_name) + return result def define_user_type(self, name, type_obj): """ @@ -2946,24 +3016,24 @@ class BinaryView(object): name = types.QualifiedName(name)._get_core_struct() core.BNDefineUserAnalysisType(self.handle, name, type_obj.handle) - def undefine_type(self, name): + def undefine_type(self, type_id): """ ``undefine_type`` removes a :py:Class:`Type` from the global list of types for the current :py:Class:`BinaryView` - :param QualifiedName name: Name of type to be undefined + :param str type_id: Unique identifier of type to be undefined :rtype: None :Example: >>> type, name = bv.parse_type_string("int foo") - >>> bv.define_type(name, type) + >>> type_id = Type.generate_auto_type_id("source", name) + >>> bv.define_type(type_id, name, type) >>> bv.get_type_by_name(name) - >>> bv.undefine_type(name) + >>> bv.undefine_type(type_id) >>> bv.get_type_by_name(name) >>> """ - name = types.QualifiedName(name)._get_core_struct() - core.BNUndefineAnalysisType(self.handle, name) + core.BNUndefineAnalysisType(self.handle, type_id) def undefine_user_type(self, name): """ @@ -2975,16 +3045,38 @@ class BinaryView(object): :Example: >>> type, name = bv.parse_type_string("int foo") - >>> bv.define_type(name, type) + >>> bv.define_user_type(name, type) >>> bv.get_type_by_name(name) - >>> bv.undefine_type(name) + >>> bv.undefine_user_type(name) >>> bv.get_type_by_name(name) >>> """ name = types.QualifiedName(name)._get_core_struct() core.BNUndefineUserAnalysisType(self.handle, name) + def rename_type(self, old_name, new_name): + """ + ``rename_type`` renames a type in the global list of types for the current :py:Class:`BinaryView` + + :param QualifiedName old_name: Existing name of type to be renamed + :param QualifiedName new_name: New name of type to be renamed + :rtype: None + :Example: + + >>> type, name = bv.parse_type_string("int foo") + >>> bv.define_user_type(name, type) + >>> bv.get_type_by_name("foo") + + >>> bv.rename_type("foo", "bar") + >>> bv.get_type_by_name("bar") + + >>> + """ + old_name = types.QualifiedName(old_name)._get_core_struct() + new_name = types.QualifiedName(new_name)._get_core_struct() + core.BNRenameAnalysisType(self.handle, old_name, new_name) + def find_next_data(self, start, data, flags = 0): """ ``find_next_data`` searchs for the bytes in data starting at the virtual address ``start`` either, case-sensitive, diff --git a/python/types.py b/python/types.py index 1dd2157e..1cc02691 100644 --- a/python/types.py +++ b/python/types.py @@ -299,7 +299,7 @@ class Type(object): result = core.BNGetTypeNamedTypeReference(self.handle) if result is None: return None - return NamedTypeReference(result) + return NamedTypeReference(handle = result) @property def count(self): @@ -392,12 +392,24 @@ class Type(object): def named_type(self, named_type, width = 0, align = 1): return Type(core.BNCreateNamedTypeReference(named_type.handle, width, align)) + @classmethod + def named_type_from_type_and_id(self, type_id, name, t): + name = QualifiedName(name)._get_core_struct() + if t is not None: + t = t.handle + return Type(core.BNCreateNamedTypeReferenceFromTypeAndId(type_id, name, t)) + @classmethod def named_type_from_type(self, name, t): name = QualifiedName(name)._get_core_struct() if t is not None: t = t.handle - return Type(core.BNCreateNamedTypeReferenceFromType(name, t)) + return Type(core.BNCreateNamedTypeReferenceFromTypeAndId("", name, t)) + + @classmethod + def named_type_from_registered_type(self, view, name): + name = QualifiedName(name)._get_core_struct() + return Type(core.BNCreateNamedTypeReferenceFromType(view.handle, name)) @classmethod def enumeration_type(self, arch, e, width=None): @@ -428,6 +440,21 @@ class Type(object): return Type(core.BNCreateFunctionType(ret.handle, calling_convention, param_buf, len(params), variable_arguments)) + @classmethod + def generate_auto_type_id(self, source, name): + name = QualifiedName(name)._get_core_struct() + return core.BNGenerateAutoTypeId(source, name) + + @classmethod + def generate_auto_platform_type_id(self, name): + name = QualifiedName(name)._get_core_struct() + return core.BNGenerateAutoTypeId(name) + + @classmethod + def generate_auto_demangled_type_id(self, name): + name = QualifiedName(name)._get_core_struct() + return core.BNGenerateAutoTypeId(name) + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) @@ -436,10 +463,12 @@ class Type(object): class NamedTypeReference(object): - def __init__(self, type_class = NamedTypeReferenceClass.UnknownNamedTypeClass, name = None, handle = None): + def __init__(self, type_class = NamedTypeReferenceClass.UnknownNamedTypeClass, type_id = None, name = None, handle = None): if handle is None: self.handle = core.BNCreateNamedType() core.BNSetTypeReferenceClass(self.handle, type_class) + if type_id is not None: + core.BNSetTypeReferenceId(self.handle, type_id) if name is not None: name = QualifiedName(name)._get_core_struct() core.BNSetTypeReferenceName(self.handle, name) @@ -451,16 +480,23 @@ class NamedTypeReference(object): @property def type_class(self): - return core.BNGetTypeReferenceClass(self.handle) + return NamedTypeReferenceClass(core.BNGetTypeReferenceClass(self.handle)) @type_class.setter def type_class(self, value): core.BNSetTypeReferenceClass(self.handle, value) + @property + def type_id(self): + return core.BNGetTypeReferenceId(self.handle) + + @type_id.setter + def type_id(self, value): + core.BNSetTypeReferenceId(self.handle, value) + @property def name(self): - count = ctypes.c_ulonglong() - name = core.BNGetTypeReferenceName(self.handle, count) + name = core.BNGetTypeReferenceName(self.handle) result = QualifiedName._from_core_struct(name) core.BNFreeQualifiedName(name) return result @@ -481,6 +517,21 @@ class NamedTypeReference(object): return "" % str(self.name) return "" % str(self.name) + @classmethod + def generate_auto_type_ref(self, type_class, source, name): + type_id = Type.generate_auto_type_id(source, name) + return NamedTypeReference(type_class, type_id, name) + + @classmethod + def generate_auto_platform_type_ref(self, type_class, source, name): + type_id = Type.generate_auto_platform_type_id(source, name) + return NamedTypeReference(type_class, type_id, name) + + @classmethod + def generate_auto_demangled_type_ref(self, type_class, source, name): + type_id = Type.generate_auto_demangled_type_id(source, name) + return NamedTypeReference(type_class, type_id, name) + class StructureMember(object): def __init__(self, t, name, offset): diff --git a/type.cpp b/type.cpp index e71077e6..dd1fb8d6 100644 --- a/type.cpp +++ b/type.cpp @@ -511,9 +511,25 @@ Ref Type::NamedType(NamedTypeReference* ref, size_t width, size_t align) Ref Type::NamedType(const QualifiedName& name, Type* type) +{ + return NamedType("", name, type); +} + + +Ref Type::NamedType(const string& id, const QualifiedName& name, Type* type) { BNQualifiedName nameObj = name.GetAPIObject(); - Type* result = new Type(BNCreateNamedTypeReferenceFromType(&nameObj, type ? type->GetObject() : nullptr)); + Type* result = new Type(BNCreateNamedTypeReferenceFromTypeAndId(id.c_str(), &nameObj, + type ? type->GetObject() : nullptr)); + QualifiedName::FreeAPIObject(&nameObj); + return result; +} + + +Ref Type::NamedType(BinaryView* view, const QualifiedName& name) +{ + BNQualifiedName nameObj = name.GetAPIObject(); + Type* result = new Type(BNCreateNamedTypeReferenceFromType(view->GetObject(), &nameObj)); QualifiedName::FreeAPIObject(&nameObj); return result; } @@ -561,16 +577,47 @@ void Type::SetFunctionCanReturn(bool canReturn) } +string Type::GenerateAutoTypeId(const string& source, const QualifiedName& name) +{ + BNQualifiedName nameObj = name.GetAPIObject(); + string result = BNGenerateAutoTypeId(source.c_str(), &nameObj); + QualifiedName::FreeAPIObject(&nameObj); + return result; +} + + +string Type::GenerateAutoPlatformTypeId(const QualifiedName& name) +{ + BNQualifiedName nameObj = name.GetAPIObject(); + string result = BNGenerateAutoPlatformTypeId(&nameObj); + QualifiedName::FreeAPIObject(&nameObj); + return result; +} + + +string Type::GenerateAutoDemangledTypeId(const QualifiedName& name) +{ + BNQualifiedName nameObj = name.GetAPIObject(); + string result = BNGenerateAutoDemangledTypeId(&nameObj); + QualifiedName::FreeAPIObject(&nameObj); + return result; +} + + NamedTypeReference::NamedTypeReference(BNNamedTypeReference* nt) { m_object = nt; } -NamedTypeReference::NamedTypeReference(BNNamedTypeReferenceClass cls, const QualifiedName& names) +NamedTypeReference::NamedTypeReference(BNNamedTypeReferenceClass cls, const string& id, const QualifiedName& names) { m_object = BNCreateNamedType(); BNSetTypeReferenceClass(m_object, cls); + if (id.size() != 0) + { + BNSetTypeReferenceId(m_object, id.c_str()); + } if (names.size() != 0) { BNQualifiedName nameObj = names.GetAPIObject(); @@ -592,6 +639,21 @@ BNNamedTypeReferenceClass NamedTypeReference::GetTypeClass() const } +string NamedTypeReference::GetTypeId() const +{ + char* str = BNGetTypeReferenceId(m_object); + string result = str; + BNFreeString(str); + return result; +} + + +void NamedTypeReference::SetTypeId(const string& id) +{ + BNSetTypeReferenceId(m_object, id.c_str()); +} + + void NamedTypeReference::SetName(const QualifiedName& names) { BNQualifiedName nameObj = names.GetAPIObject(); @@ -609,6 +671,30 @@ QualifiedName NamedTypeReference::GetName() const } +Ref NamedTypeReference::GenerateAutoTypeReference(BNNamedTypeReferenceClass cls, + const string& source, const QualifiedName& name) +{ + string id = Type::GenerateAutoTypeId(source, name); + return new NamedTypeReference(cls, id, name); +} + + +Ref NamedTypeReference::GenerateAutoPlatformTypeReference(BNNamedTypeReferenceClass cls, + const QualifiedName& name) +{ + string id = Type::GenerateAutoPlatformTypeId(name); + return new NamedTypeReference(cls, id, name); +} + + +Ref NamedTypeReference::GenerateAutoDemangledTypeReference(BNNamedTypeReferenceClass cls, + const QualifiedName& name) +{ + string id = Type::GenerateAutoDemangledTypeId(name); + return new NamedTypeReference(cls, id, name); +} + + Structure::Structure() { m_object = BNCreateStructure(); -- cgit v1.3.1 From 57088dfd10ebbc5361e1493c034dec8ed6730bdc Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Thu, 23 Feb 2017 02:20:55 -0500 Subject: add get_install_directory and savelastrun to the api --- binaryninjaapi.cpp | 11 +++++++++++ binaryninjaapi.h | 1 + binaryninjacore.h | 4 ++++ python/__init__.py | 9 +++++++++ 4 files changed, 25 insertions(+) (limited to 'python/__init__.py') diff --git a/binaryninjaapi.cpp b/binaryninjaapi.cpp index 6b303bcd..68cc2f43 100644 --- a/binaryninjaapi.cpp +++ b/binaryninjaapi.cpp @@ -59,6 +59,17 @@ void BinaryNinja::SetBundledPluginDirectory(const string& path) } +string BinaryNinja::GetInstallDirectory() +{ + char* path = BNGetInstallDirectory(); + if (!path) + return string(); + string result = path; + BNFreeString(path); + return result; +} + + string BinaryNinja::GetUserPluginDirectory() { char* path = BNGetUserPluginDirectory(); diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 6b69c95f..b8b684be 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -376,6 +376,7 @@ namespace BinaryNinja void InitUserPlugins(); std::string GetBundledPluginDirectory(); void SetBundledPluginDirectory(const std::string& path); + std::string GetInstallDirectory(); std::string GetUserPluginDirectory(); std::string GetPathRelativeToBundledPluginDirectory(const std::string& path); diff --git a/binaryninjacore.h b/binaryninjacore.h index d1c7f4d2..62889a4d 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1247,10 +1247,14 @@ extern "C" // Plugin initialization BINARYNINJACOREAPI void BNInitCorePlugins(void); BINARYNINJACOREAPI void BNInitUserPlugins(void); + BINARYNINJACOREAPI char* BNGetInstallDirectory(void); BINARYNINJACOREAPI char* BNGetBundledPluginDirectory(void); BINARYNINJACOREAPI void BNSetBundledPluginDirectory(const char* path); + BINARYNINJACOREAPI char* BNGetUserDirectory(void); BINARYNINJACOREAPI char* BNGetUserPluginDirectory(void); + BINARYNINJACOREAPI void BNSaveLastRun(void); + BINARYNINJACOREAPI char* BNGetPathRelativeToBundledPluginDirectory(const char* path); BINARYNINJACOREAPI char* BNGetPathRelativeToUserPluginDirectory(const char* path); diff --git a/python/__init__.py b/python/__init__.py index b1f5cd08..dcbb8276 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -58,6 +58,15 @@ def get_unique_identifier(): return core.BNGetUniqueIdentifierString() +def get_install_directory(): + """ + ``get_install_directory`` returns a string pointing to the installed binary currently running + + .warning:: ONLY for use within the Binary Ninja UI, behavior is undefined and unreliable if run headlessly + """ + return core.BNGetInstallDirectory() + + class _DestructionCallbackHandler(object): def __init__(self): self._cb = core.BNObjectDestructionCallbacks() -- cgit v1.3.1 From 94b38cee51eff16f1e79945806088c7ae60016d7 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Wed, 1 Mar 2017 03:45:51 -0500 Subject: Adding framework for medium level IL --- binaryninjaapi.h | 70 +++++++ binaryninjacore.h | 174 +++++++++++++++- function.cpp | 12 +- lowlevelil.cpp | 6 +- mediumlevelil.cpp | 378 ++++++++++++++++++++++++++++++++++ python/__init__.py | 1 + python/function.py | 20 +- python/lowlevelil.py | 8 +- python/mediumlevelil.py | 525 ++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 1179 insertions(+), 15 deletions(-) create mode 100644 mediumlevelil.cpp create mode 100644 python/mediumlevelil.py (limited to 'python/__init__.py') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 58ea890e..1367e7c1 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1862,6 +1862,7 @@ namespace BinaryNinja }; class FunctionGraph; + class MediumLevelILFunction; class Function: public CoreRefCountObject { @@ -1913,6 +1914,8 @@ namespace BinaryNinja std::set GetFlagsReadByLiftedILInstruction(size_t i); std::set GetFlagsWrittenByLiftedILInstruction(size_t i); + Ref GetMediumLevelIL() const; + Ref GetType() const; void SetAutoType(Type* type); void SetUserType(Type* type); @@ -2182,6 +2185,73 @@ namespace BinaryNinja RegisterValue GetExprValue(size_t expr); }; + struct MediumLevelILLabel: public BNMediumLevelILLabel + { + MediumLevelILLabel(); + }; + + class MediumLevelILFunction: public CoreRefCountObject + { + public: + MediumLevelILFunction(Architecture* arch, Function* func = nullptr); + MediumLevelILFunction(BNMediumLevelILFunction* func); + + uint64_t GetCurrentAddress() const; + void SetCurrentAddress(Architecture* arch, uint64_t addr); + size_t GetInstructionStart(Architecture* arch, uint64_t addr); + + ExprId AddExpr(BNMediumLevelILOperation operation, size_t size, + ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0); + ExprId AddInstruction(ExprId expr); + + ExprId SetVar(size_t size, const BNILVariable& var, ExprId src); + ExprId SetVarField(size_t size, const BNILVariable& var, int64_t offset, ExprId src); + ExprId SetVarSSA(size_t size, const BNILVariable& var, size_t index, ExprId src); + ExprId SetVarFieldSSA(size_t size, const BNILVariable& var, int64_t offset, size_t varIndex, ExprId src); + ExprId Var(size_t size, const BNILVariable& var); + ExprId VarField(size_t size, const BNILVariable& var, int64_t offset); + ExprId VarSSA(size_t size, const BNILVariable& var, size_t index); + ExprId VarFieldSSA(size_t size, const BNILVariable& var, int64_t offset, size_t varIndex); + + ExprId Goto(BNMediumLevelILLabel& label); + ExprId If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f); + void MarkLabel(BNMediumLevelILLabel& label); + + std::vector GetOperandList(ExprId i, size_t listOperand); + ExprId AddLabelList(const std::vector& labels); + ExprId AddOperandList(const std::vector operands); + + BNILVariable GetVariable(ExprId i, size_t varOperand); + + BNMediumLevelILInstruction operator[](size_t i) const; + size_t GetIndexForInstruction(size_t i) const; + size_t GetInstructionCount() const; + + void Finalize(); + + bool GetExprText(Architecture* arch, ExprId expr, std::vector& tokens); + bool GetInstructionText(Function* func, Architecture* arch, size_t i, + std::vector& tokens); + + std::vector> GetBasicBlocks() const; + + Ref GetSSAForm() const; + Ref GetNonSSAForm() const; + size_t GetSSAInstructionIndex(size_t instr) const; + size_t GetNonSSAInstructionIndex(size_t instr) const; + size_t GetSSAExprIndex(size_t instr) const; + size_t GetNonSSAExprIndex(size_t instr) const; + + size_t GetSSAVarDefinition(const BNILVariable& var, size_t idx) const; + size_t GetSSAMemoryDefinition(size_t idx) const; + std::set GetSSAVarUses(const BNILVariable& var, size_t idx) const; + std::set GetSSAMemoryUses(size_t idx) const; + + RegisterValue GetSSAVarValue(const BNILVariable& var, size_t idx); + RegisterValue GetExprValue(size_t expr); + }; + class FunctionRecognizer { static bool RecognizeLowLevelILCallback(void* ctxt, BNBinaryView* data, BNFunction* func, BNLowLevelILFunction* il); diff --git a/binaryninjacore.h b/binaryninjacore.h index 89302c64..aa9bb49b 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -92,6 +92,7 @@ extern "C" struct BNSymbol; struct BNTemporaryFile; struct BNLowLevelILFunction; + struct BNMediumLevelILFunction; struct BNType; struct BNStructure; struct BNNamedTypeReference; @@ -363,7 +364,9 @@ extern "C" NormalFunctionGraph = 0, LowLevelILFunctionGraph = 1, LiftedILFunctionGraph = 2, - LowLevelILSSAFormFunctionGraph = 3 + LowLevelILSSAFormFunctionGraph = 3, + MediumLevelILFunctionGraph = 4, + MediumLevelILSSAFormFunctionGraph = 5 }; enum BNDisassemblyOption @@ -637,6 +640,115 @@ extern "C" bool autoDiscovered; }; + enum BNMediumLevelILOperation + { + MLIL_NOP, + MLIL_SET_VAR, // Not valid in SSA form (see MLIL_SET_VAR_SSA) + MLIL_SET_VAR_FIELD, // Not valid in SSA form (see MLIL_SET_VAR_FIELD) + MLIL_LOAD, // Not valid in SSA form (see MLIL_LOAD_SSA) + MLIL_STORE, // Not valid in SSA form (see MLIL_STORE_SSA) + MLIL_VAR, // Not valid in SSA form (see MLIL_VAR_SSA) + MLIL_VAR_FIELD, // Not valid in SSA form (see MLIL_VAR_SSA_FIELD) + MLIL_CONST, + MLIL_ADD, + MLIL_ADC, + MLIL_SUB, + MLIL_SBB, + MLIL_AND, + MLIL_OR, + MLIL_XOR, + MLIL_LSL, + MLIL_LSR, + MLIL_ASR, + MLIL_ROL, + MLIL_RLC, + MLIL_ROR, + MLIL_RRC, + MLIL_MUL, + MLIL_MULU_DP, + MLIL_MULS_DP, + MLIL_DIVU, + MLIL_DIVU_DP, + MLIL_DIVS, + MLIL_DIVS_DP, + MLIL_MODU, + MLIL_MODU_DP, + MLIL_MODS, + MLIL_MODS_DP, + MLIL_NEG, + MLIL_NOT, + MLIL_SX, + MLIL_ZX, + MLIL_JUMP, + MLIL_JUMP_TO, + MLIL_CALL, + MLIL_RET, + MLIL_NORET, + MLIL_IF, + MLIL_GOTO, + MLIL_CMP_E, + MLIL_CMP_NE, + MLIL_CMP_SLT, + MLIL_CMP_ULT, + MLIL_CMP_SLE, + MLIL_CMP_ULE, + MLIL_CMP_SGE, + MLIL_CMP_UGE, + MLIL_CMP_SGT, + MLIL_CMP_UGT, + MLIL_TEST_BIT, + MLIL_BOOL_TO_INT, + MLIL_SYSCALL, + MLIL_BP, + MLIL_TRAP, + MLIL_UNDEF, + MLIL_UNIMPL, + MLIL_UNIMPL_MEM, + + // The following instructions are only used in SSA form + MLIL_SET_VAR_SSA, + MLIL_SET_VAR_SSA_FIELD, + MLIL_VAR_SSA, + MLIL_VAR_SSA_FIELD, + MLIL_CALL_SSA, + MLIL_SYSCALL_SSA, + MLIL_CALL_PARAM_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions + MLIL_CALL_OUTPUT_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions + MLIL_LOAD_SSA, + MLIL_STORE_SSA, + MLIL_VAR_PHI, + MLIL_MEM_PHI + }; + + struct BNMediumLevelILInstruction + { + BNMediumLevelILOperation operation; + size_t size; + uint64_t operands[5]; + uint64_t address; + }; + + struct BNMediumLevelILLabel + { + bool resolved; + size_t ref; + size_t operand; + }; + + enum BNILVariableSourceType + { + RegisterVariableSourceType, + FlagVariableSourceType, + StackVariableSourceType + }; + + struct BNILVariable + { + BNILVariableSourceType type; + uint32_t index; + int64_t identifier; + }; + // Callbacks struct BNLogListener { @@ -1698,7 +1810,8 @@ extern "C" BINARYNINJACOREAPI size_t BNGetLowLevelILForInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI size_t* BNGetLowLevelILExitsForInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, size_t* count); - BINARYNINJACOREAPI void BNFreeLowLevelILInstructionList(size_t* list); + BINARYNINJACOREAPI void BNFreeILInstructionList(size_t* list); + BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetFunctionMediumLevelIL(BNFunction* func); BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAtInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, uint32_t reg); BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAfterInstruction(BNFunction* func, BNArchitecture* arch, @@ -2043,6 +2156,63 @@ extern "C" BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILExprValue(BNLowLevelILFunction* func, size_t expr); + // Medium-level IL + BINARYNINJACOREAPI BNMediumLevelILFunction* BNCreateMediumLevelILFunction(BNArchitecture* arch, BNFunction* func); + BINARYNINJACOREAPI BNMediumLevelILFunction* BNNewMediumLevelILFunctionReference(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI void BNFreeMediumLevelILFunction(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI uint64_t BNMediumLevelILGetCurrentAddress(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI void BNMediumLevelILSetCurrentAddress(BNMediumLevelILFunction* func, + BNArchitecture* arch, uint64_t addr); + BINARYNINJACOREAPI size_t BNMediumLevelILGetInstructionStart(BNMediumLevelILFunction* func, + BNArchitecture* arch, uint64_t addr); + BINARYNINJACOREAPI size_t BNMediumLevelILAddExpr(BNMediumLevelILFunction* func, BNMediumLevelILOperation operation, + size_t size, uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e); + BINARYNINJACOREAPI size_t BNMediumLevelILAddInstruction(BNMediumLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI size_t BNMediumLevelILGoto(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label); + BINARYNINJACOREAPI size_t BNMediumLevelILIf(BNMediumLevelILFunction* func, uint64_t op, + BNMediumLevelILLabel* t, BNMediumLevelILLabel* f); + BINARYNINJACOREAPI void BNMediumLevelILInitLabel(BNMediumLevelILLabel* label); + BINARYNINJACOREAPI void BNMediumLevelILMarkLabel(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label); + BINARYNINJACOREAPI void BNFinalizeMediumLevelILFunction(BNMediumLevelILFunction* func); + + BINARYNINJACOREAPI size_t BNMediumLevelILAddLabelList(BNMediumLevelILFunction* func, + BNMediumLevelILLabel** labels, size_t count); + BINARYNINJACOREAPI size_t BNMediumLevelILAddOperandList(BNMediumLevelILFunction* func, + uint64_t* operands, size_t count); + BINARYNINJACOREAPI uint64_t* BNMediumLevelILGetOperandList(BNMediumLevelILFunction* func, size_t expr, + size_t operand, size_t* count); + BINARYNINJACOREAPI void BNMediumLevelILFreeOperandList(uint64_t* operands); + + BINARYNINJACOREAPI BNMediumLevelILInstruction BNGetMediumLevelILByIndex(BNMediumLevelILFunction* func, size_t i); + BINARYNINJACOREAPI size_t BNGetMediumLevelILIndexForInstruction(BNMediumLevelILFunction* func, size_t i); + BINARYNINJACOREAPI size_t BNGetMediumLevelILInstructionCount(BNMediumLevelILFunction* func); + + BINARYNINJACOREAPI bool BNGetMediumLevelILExprText(BNMediumLevelILFunction* func, BNArchitecture* arch, size_t i, + BNInstructionTextToken** tokens, size_t* count); + BINARYNINJACOREAPI bool BNGetMediumLevelILInstructionText(BNMediumLevelILFunction* il, BNFunction* func, + BNArchitecture* arch, size_t i, BNInstructionTextToken** tokens, size_t* count); + + BINARYNINJACOREAPI BNBasicBlock** BNGetMediumLevelILBasicBlockList(BNMediumLevelILFunction* func, size_t* count); + + BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMediumLevelILSSAForm(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMediumLevelILNonSSAForm(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAInstructionIndex(BNMediumLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI size_t BNGetMediumLevelILNonSSAInstructionIndex(BNMediumLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAExprIndex(BNMediumLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI size_t BNGetMediumLevelILNonSSAExprIndex(BNMediumLevelILFunction* func, size_t expr); + + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAVarDefinition(BNMediumLevelILFunction* func, + const BNILVariable* var, size_t idx); + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAMemoryDefinition(BNMediumLevelILFunction* func, size_t idx); + BINARYNINJACOREAPI size_t* BNGetMediumLevelILSSAVarUses(BNMediumLevelILFunction* func, const BNILVariable* var, + size_t idx, size_t* count); + BINARYNINJACOREAPI size_t* BNGetMediumLevelILSSAMemoryUses(BNMediumLevelILFunction* func, + size_t idx, size_t* count); + + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILSSAVarValue(BNMediumLevelILFunction* func, + const BNILVariable* var, size_t idx); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILExprValue(BNMediumLevelILFunction* func, size_t expr); + // Types BINARYNINJACOREAPI BNType* BNCreateVoidType(void); BINARYNINJACOREAPI BNType* BNCreateBoolType(void); diff --git a/function.cpp b/function.cpp index fe119c9d..9faf68fa 100644 --- a/function.cpp +++ b/function.cpp @@ -161,7 +161,7 @@ vector Function::GetLowLevelILExitsForInstruction(Architecture* arch, ui vector result; result.insert(result.end(), exits, &exits[count]); - BNFreeLowLevelILInstructionList(exits); + BNFreeILInstructionList(exits); return result; } @@ -343,7 +343,7 @@ set Function::GetLiftedILFlagUsesForDefinition(size_t i, uint32_t flag) set result; result.insert(&instrs[0], &instrs[count]); - BNFreeLowLevelILInstructionList(instrs); + BNFreeILInstructionList(instrs); return result; } @@ -355,7 +355,7 @@ set Function::GetLiftedILFlagDefinitionsForUse(size_t i, uint32_t flag) set result; result.insert(&instrs[0], &instrs[count]); - BNFreeLowLevelILInstructionList(instrs); + BNFreeILInstructionList(instrs); return result; } @@ -384,6 +384,12 @@ set Function::GetFlagsWrittenByLiftedILInstruction(size_t i) } +Ref Function::GetMediumLevelIL() const +{ + return new MediumLevelILFunction(BNGetFunctionMediumLevelIL(m_object)); +} + + Ref Function::GetType() const { return new Type(BNGetFunctionType(m_object)); diff --git a/lowlevelil.cpp b/lowlevelil.cpp index fecde9c8..5a789981 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -720,7 +720,7 @@ set LowLevelILFunction::GetSSARegisterUses(uint32_t reg, size_t idx) con for (size_t i = 0; i < count; i++) result.insert(instrs[i]); - BNFreeLowLevelILInstructionList(instrs); + BNFreeILInstructionList(instrs); return result; } @@ -734,7 +734,7 @@ set LowLevelILFunction::GetSSAFlagUses(uint32_t flag, size_t idx) const for (size_t i = 0; i < count; i++) result.insert(instrs[i]); - BNFreeLowLevelILInstructionList(instrs); + BNFreeILInstructionList(instrs); return result; } @@ -748,7 +748,7 @@ set LowLevelILFunction::GetSSAMemoryUses(size_t idx) const for (size_t i = 0; i < count; i++) result.insert(instrs[i]); - BNFreeLowLevelILInstructionList(instrs); + BNFreeILInstructionList(instrs); return result; } diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp new file mode 100644 index 00000000..f6ad5bfd --- /dev/null +++ b/mediumlevelil.cpp @@ -0,0 +1,378 @@ +// Copyright (c) 2017 Vector 35 LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#include "binaryninjaapi.h" + +using namespace BinaryNinja; +using namespace std; + + +MediumLevelILLabel::MediumLevelILLabel() +{ + BNMediumLevelILInitLabel(this); +} + + +MediumLevelILFunction::MediumLevelILFunction(Architecture* arch, Function* func) +{ + m_object = BNCreateMediumLevelILFunction(arch->GetObject(), func ? func->GetObject() : nullptr); +} + + +MediumLevelILFunction::MediumLevelILFunction(BNMediumLevelILFunction* func) +{ + m_object = func; +} + + +uint64_t MediumLevelILFunction::GetCurrentAddress() const +{ + return BNMediumLevelILGetCurrentAddress(m_object); +} + + +void MediumLevelILFunction::SetCurrentAddress(Architecture* arch, uint64_t addr) +{ + BNMediumLevelILSetCurrentAddress(m_object, arch ? arch->GetObject() : nullptr, addr); +} + + +size_t MediumLevelILFunction::GetInstructionStart(Architecture* arch, uint64_t addr) +{ + return BNMediumLevelILGetInstructionStart(m_object, arch ? arch->GetObject() : nullptr, addr); +} + + +ExprId MediumLevelILFunction::AddExpr(BNMediumLevelILOperation operation, size_t size, + ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) +{ + return BNMediumLevelILAddExpr(m_object, operation, size, a, b, c, d, e); +} + + +ExprId MediumLevelILFunction::AddInstruction(size_t expr) +{ + return BNMediumLevelILAddInstruction(m_object, expr); +} + + +ExprId MediumLevelILFunction::SetVar(size_t size, const BNILVariable& var, ExprId src) +{ + return AddExpr(MLIL_SET_VAR, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, src); +} + + +ExprId MediumLevelILFunction::SetVarField(size_t size, const BNILVariable& var, int64_t offset, ExprId src) +{ + return AddExpr(MLIL_SET_VAR_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, + offset, src); +} + + +ExprId MediumLevelILFunction::SetVarSSA(size_t size, const BNILVariable& var, size_t varIndex, ExprId src) +{ + return AddExpr(MLIL_SET_VAR_SSA, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, + varIndex, src); +} + + +ExprId MediumLevelILFunction::SetVarFieldSSA(size_t size, const BNILVariable& var, int64_t offset, + size_t varIndex, ExprId src) +{ + return AddExpr(MLIL_SET_VAR_SSA_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, + offset, varIndex, src); +} + + +ExprId MediumLevelILFunction::Var(size_t size, const BNILVariable& var) +{ + return AddExpr(MLIL_VAR, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier); +} + + +ExprId MediumLevelILFunction::VarField(size_t size, const BNILVariable& var, int64_t offset) +{ + return AddExpr(MLIL_VAR_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, offset); +} + + +ExprId MediumLevelILFunction::VarSSA(size_t size, const BNILVariable& var, size_t varIndex) +{ + return AddExpr(MLIL_VAR_SSA, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, varIndex); +} + + +ExprId MediumLevelILFunction::VarFieldSSA(size_t size, const BNILVariable& var, int64_t offset, + size_t varIndex) +{ + return AddExpr(MLIL_VAR_SSA_FIELD, size, ((uint64_t)var.type << 32) | (uint64_t)var.index, var.identifier, + offset, varIndex); +} + + +ExprId MediumLevelILFunction::Goto(BNMediumLevelILLabel& label) +{ + return BNMediumLevelILGoto(m_object, &label); +} + + +ExprId MediumLevelILFunction::If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f) +{ + return BNMediumLevelILIf(m_object, operand, &t, &f); +} + + +void MediumLevelILFunction::MarkLabel(BNMediumLevelILLabel& label) +{ + BNMediumLevelILMarkLabel(m_object, &label); +} + + +vector MediumLevelILFunction::GetOperandList(ExprId expr, size_t listOperand) +{ + size_t count; + uint64_t* operands = BNMediumLevelILGetOperandList(m_object, expr, listOperand, &count); + vector result; + for (size_t i = 0; i < count; i++) + result.push_back(operands[i]); + BNMediumLevelILFreeOperandList(operands); + return result; +} + + +ExprId MediumLevelILFunction::AddLabelList(const vector& labels) +{ + BNMediumLevelILLabel** labelList = new BNMediumLevelILLabel*[labels.size()]; + for (size_t i = 0; i < labels.size(); i++) + labelList[i] = labels[i]; + ExprId result = (ExprId)BNMediumLevelILAddLabelList(m_object, labelList, labels.size()); + delete[] labelList; + return result; +} + + +ExprId MediumLevelILFunction::AddOperandList(const vector operands) +{ + uint64_t* operandList = new uint64_t[operands.size()]; + for (size_t i = 0; i < operands.size(); i++) + operandList[i] = operands[i]; + ExprId result = (ExprId)BNMediumLevelILAddOperandList(m_object, operandList, operands.size()); + delete[] operandList; + return result; +} + + +BNILVariable MediumLevelILFunction::GetVariable(ExprId i, size_t varOperand) +{ + BNMediumLevelILInstruction instr = (*this)[i]; + BNILVariable result; + result.type = (BNILVariableSourceType)(instr.operands[varOperand] >> 32); + result.index = (uint32_t)instr.operands[varOperand]; + result.identifier = instr.operands[varOperand + 1]; + return result; +} + + +BNMediumLevelILInstruction MediumLevelILFunction::operator[](size_t i) const +{ + return BNGetMediumLevelILByIndex(m_object, i); +} + + +size_t MediumLevelILFunction::GetIndexForInstruction(size_t i) const +{ + return BNGetMediumLevelILIndexForInstruction(m_object, i); +} + + +size_t MediumLevelILFunction::GetInstructionCount() const +{ + return BNGetMediumLevelILInstructionCount(m_object); +} + + +void MediumLevelILFunction::Finalize() +{ + BNFinalizeMediumLevelILFunction(m_object); +} + + +bool MediumLevelILFunction::GetExprText(Architecture* arch, ExprId expr, vector& tokens) +{ + size_t count; + BNInstructionTextToken* list; + if (!BNGetMediumLevelILExprText(m_object, arch->GetObject(), expr, &list, &count)) + return false; + + tokens.clear(); + for (size_t i = 0; i < count; i++) + { + InstructionTextToken token; + token.type = list[i].type; + token.text = list[i].text; + token.value = list[i].value; + token.size = list[i].size; + token.operand = list[i].operand; + token.context = list[i].context; + token.address = list[i].address; + tokens.push_back(token); + } + + BNFreeInstructionText(list, count); + return true; +} + + +bool MediumLevelILFunction::GetInstructionText(Function* func, Architecture* arch, size_t instr, + vector& tokens) +{ + size_t count; + BNInstructionTextToken* list; + if (!BNGetMediumLevelILInstructionText(m_object, func ? func->GetObject() : nullptr, arch->GetObject(), + instr, &list, &count)) + return false; + + tokens.clear(); + for (size_t i = 0; i < count; i++) + { + InstructionTextToken token; + token.type = list[i].type; + token.text = list[i].text; + token.value = list[i].value; + token.size = list[i].size; + token.operand = list[i].operand; + token.context = list[i].context; + token.address = list[i].address; + tokens.push_back(token); + } + + BNFreeInstructionText(list, count); + return true; +} + + +vector> MediumLevelILFunction::GetBasicBlocks() const +{ + size_t count; + BNBasicBlock** blocks = BNGetMediumLevelILBasicBlockList(m_object, &count); + + vector> result; + for (size_t i = 0; i < count; i++) + result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); + + BNFreeBasicBlockList(blocks, count); + return result; +} + + +Ref MediumLevelILFunction::GetSSAForm() const +{ + BNMediumLevelILFunction* func = BNGetMediumLevelILSSAForm(m_object); + if (!func) + return nullptr; + return new MediumLevelILFunction(func); +} + + +Ref MediumLevelILFunction::GetNonSSAForm() const +{ + BNMediumLevelILFunction* func = BNGetMediumLevelILNonSSAForm(m_object); + if (!func) + return nullptr; + return new MediumLevelILFunction(func); +} + + +size_t MediumLevelILFunction::GetSSAInstructionIndex(size_t instr) const +{ + return BNGetMediumLevelILSSAInstructionIndex(m_object, instr); +} + + +size_t MediumLevelILFunction::GetNonSSAInstructionIndex(size_t instr) const +{ + return BNGetMediumLevelILNonSSAInstructionIndex(m_object, instr); +} + + +size_t MediumLevelILFunction::GetSSAExprIndex(size_t expr) const +{ + return BNGetMediumLevelILSSAExprIndex(m_object, expr); +} + + +size_t MediumLevelILFunction::GetNonSSAExprIndex(size_t expr) const +{ + return BNGetMediumLevelILNonSSAExprIndex(m_object, expr); +} + + +size_t MediumLevelILFunction::GetSSAVarDefinition(const BNILVariable& var, size_t idx) const +{ + return BNGetMediumLevelILSSAVarDefinition(m_object, &var, idx); +} + + +size_t MediumLevelILFunction::GetSSAMemoryDefinition(size_t idx) const +{ + return BNGetMediumLevelILSSAMemoryDefinition(m_object, idx); +} + + +set MediumLevelILFunction::GetSSAVarUses(const BNILVariable& var, size_t idx) const +{ + size_t count; + size_t* instrs = BNGetMediumLevelILSSAVarUses(m_object, &var, idx, &count); + + set result; + for (size_t i = 0; i < count; i++) + result.insert(instrs[i]); + + BNFreeILInstructionList(instrs); + return result; +} + + +set MediumLevelILFunction::GetSSAMemoryUses(size_t idx) const +{ + size_t count; + size_t* instrs = BNGetMediumLevelILSSAMemoryUses(m_object, idx, &count); + + set result; + for (size_t i = 0; i < count; i++) + result.insert(instrs[i]); + + BNFreeILInstructionList(instrs); + return result; +} + + +RegisterValue MediumLevelILFunction::GetSSAVarValue(const BNILVariable& var, size_t idx) +{ + BNRegisterValue value = BNGetMediumLevelILSSAVarValue(m_object, &var, idx); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetExprValue(size_t expr) +{ + BNRegisterValue value = BNGetMediumLevelILExprValue(m_object, expr); + return RegisterValue::FromAPIObject(value); +} diff --git a/python/__init__.py b/python/__init__.py index b1f5cd08..7502d205 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -32,6 +32,7 @@ from .basicblock import * from .function import * from .log import * from .lowlevelil import * +from .mediumlevelil import * from .types import * from .functionrecognizer import * from .update import * diff --git a/python/function.py b/python/function.py index 07187080..ed2a537c 100644 --- a/python/function.py +++ b/python/function.py @@ -33,6 +33,7 @@ import associateddatastore import types import basicblock import lowlevelil +import mediumlevelil import binaryview import log @@ -139,6 +140,14 @@ class StackVariableReference(object): return "" % (self.source_operand, self.name) +class ILVariable(object): + def __init__(self, func, var_type, index, identifier): + self.function = func + self.type = var_type + self.index = index + self.identifier = identifier + + class ConstantReference(object): def __init__(self, val, size): self.value = val @@ -299,6 +308,11 @@ class Function(object): """Function lifted IL (read-only)""" return lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLiftedIL(self.handle), self) + @property + def medium_level_il(self): + """Function medium level IL (read-only)""" + return mediumlevelil.MediumLevelILFunction(self.arch, core.BNGetFunctionMediumLevelIL(self.handle), self) + @property def function_type(self): """Function type object""" @@ -398,7 +412,7 @@ class Function(object): result = [] for i in xrange(0, count.value): result.append(exits[i]) - core.BNFreeLowLevelILInstructionList(exits) + core.BNFreeILInstructionList(exits) return result def get_reg_value_at(self, addr, reg, arch=None): @@ -597,7 +611,7 @@ class Function(object): result = [] for i in xrange(0, count.value): result.append(instrs[i]) - core.BNFreeLowLevelILInstructionList(instrs) + core.BNFreeILInstructionList(instrs) return result def get_lifted_il_flag_definitions_for_use(self, i, flag): @@ -608,7 +622,7 @@ class Function(object): result = [] for i in xrange(0, count.value): result.append(instrs[i]) - core.BNFreeLowLevelILInstructionList(instrs) + core.BNFreeILInstructionList(instrs) return result def get_flags_read_by_lifted_il_instruction(self, i): diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 6ed179c2..ed1cedd4 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -124,7 +124,7 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_SYSCALL_SSA: [("output", "expr"), ("stack", "expr"), ("param", "expr")], LowLevelILOperation.LLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "reg_ssa_list")], LowLevelILOperation.LLIL_CALL_STACK_SSA: [("src", "reg"), ("index", "int"), ("src_memory", "int")], - LowLevelILOperation.LLIL_CALL_PARAM_SSA: [("dest", "reg_ssa_list")], + LowLevelILOperation.LLIL_CALL_PARAM_SSA: [("src", "reg_ssa_list")], LowLevelILOperation.LLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")], LowLevelILOperation.LLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], LowLevelILOperation.LLIL_REG_PHI: [("dest", "reg"), ("index", "int"), ("src", "reg_ssa_list")], @@ -1385,7 +1385,7 @@ class LowLevelILFunction(object): result = [] for i in xrange(0, count.value): result.append(instrs[i]) - core.BNFreeLowLevelILInstructionList(instrs) + core.BNFreeILInstructionList(instrs) return result def get_ssa_flag_uses(self, flag, index): @@ -1394,7 +1394,7 @@ class LowLevelILFunction(object): result = [] for i in xrange(0, count.value): result.append(instrs[i]) - core.BNFreeLowLevelILInstructionList(instrs) + core.BNFreeILInstructionList(instrs) return result def get_ssa_memory_uses(self, index): @@ -1403,7 +1403,7 @@ class LowLevelILFunction(object): result = [] for i in xrange(0, count.value): result.append(instrs[i]) - core.BNFreeLowLevelILInstructionList(instrs) + core.BNFreeILInstructionList(instrs) return result def get_ssa_reg_value(self, reg, index): diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py new file mode 100644 index 00000000..c4c4aa23 --- /dev/null +++ b/python/mediumlevelil.py @@ -0,0 +1,525 @@ +# Copyright (c) 2017 Vector 35 LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import ctypes + +# Binary Ninja components +import _binaryninjacore as core +from .enums import MediumLevelILOperation, InstructionTextTokenType, ILVariableSourceType +import function +import basicblock + + +class MediumLevelILLabel(object): + def __init__(self, handle = None): + if handle is None: + self.handle = (core.BNMediumLevelILLabel * 1)() + core.BNMediumLevelILInitLabel(self.handle) + else: + self.handle = handle + + +class MediumLevelILInstruction(object): + """ + ``class MediumLevelILInstruction`` Medium Level Intermediate Language Instructions are infinite length tree-based + instructions. Tree-based instructions use infix notation with the left hand operand being the destination operand. + Infix notation is thus more natural to read than other notations (e.g. x86 ``mov eax, 0`` vs. MLIL ``eax = 0``). + """ + + ILOperations = { + MediumLevelILOperation.MLIL_NOP: [], + MediumLevelILOperation.MLIL_SET_VAR: [("dest", "var"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_FIELD: [("dest", "var"), ("offset", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_LOAD: [("src", "expr")], + MediumLevelILOperation.MLIL_STORE: [("dest", "expr"), ("src", "expr")], + MediumLevelILOperation.MLIL_VAR: [("src", "var")], + MediumLevelILOperation.MLIL_VAR_FIELD: [("src", "var"), ("offset", "int")], + MediumLevelILOperation.MLIL_CONST: [("constant", "int")], + MediumLevelILOperation.MLIL_ADD: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_SUB: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_SBB: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_AND: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_OR: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_XOR: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_LSL: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_LSR: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_ASR: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_ROL: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_RLC: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_ROR: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_RRC: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MUL: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MULU_DP: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MULS_DP: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_DIVU: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_DIVU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_DIVS: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_DIVS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MODU: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MODU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MODS: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MODS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_NEG: [("src", "expr")], + MediumLevelILOperation.MLIL_NOT: [("src", "expr")], + MediumLevelILOperation.MLIL_SX: [("src", "expr")], + MediumLevelILOperation.MLIL_ZX: [("src", "expr")], + MediumLevelILOperation.MLIL_JUMP: [("dest", "expr")], + MediumLevelILOperation.MLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], + MediumLevelILOperation.MLIL_CALL: [("dest", "expr")], + MediumLevelILOperation.MLIL_RET: [], + MediumLevelILOperation.MLIL_NORET: [], + MediumLevelILOperation.MLIL_IF: [("condition", "expr"), ("true", "int"), ("false", "int")], + MediumLevelILOperation.MLIL_GOTO: [("dest", "int")], + MediumLevelILOperation.MLIL_CMP_E: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_NE: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_SLT: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_ULT: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_SLE: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_ULE: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_SGE: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_UGE: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_SGT: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_UGT: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_TEST_BIT: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_BOOL_TO_INT: [("src", "expr")], + MediumLevelILOperation.MLIL_SYSCALL: [], + MediumLevelILOperation.MLIL_BP: [], + MediumLevelILOperation.MLIL_TRAP: [("vector", "int")], + MediumLevelILOperation.MLIL_UNDEF: [], + MediumLevelILOperation.MLIL_UNIMPL: [], + MediumLevelILOperation.MLIL_UNIMPL_MEM: [("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SSA: [("dest", "var"), ("index", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("dest", "var"), ("index", "int"), ("offset", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var"), ("index", "int")], + MediumLevelILOperation.MLIL_VAR_SSA_FIELD: [("src", "var"), ("index", "int"), ("offset", "int")], + MediumLevelILOperation.MLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("param", "expr")], + MediumLevelILOperation.MLIL_SYSCALL_SSA: [("output", "expr"), ("param", "expr")], + MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "var_ssa_list")], + MediumLevelILOperation.MLIL_CALL_PARAM_SSA: [("src", "var_ssa_list")], + MediumLevelILOperation.MLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")], + MediumLevelILOperation.MLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_VAR_PHI: [("dest", "var"), ("index", "int"), ("src", "var_ssa_list")], + MediumLevelILOperation.MLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")] + } + + def __init__(self, func, expr_index, instr_index=None): + instr = core.BNGetMediumLevelILByIndex(func.handle, expr_index) + self.function = func + self.expr_index = expr_index + self.instr_index = instr_index + self.operation = MediumLevelILOperation(instr.operation) + self.size = instr.size + self.address = instr.address + operands = MediumLevelILInstruction.ILOperations[instr.operation] + self.operands = [] + i = 0 + while i < len(operands): + name, operand_type = operands[i] + if operand_type == "int": + value = instr.operands[i] + elif operand_type == "expr": + value = MediumLevelILInstruction(func, instr.operands[i]) + elif operand_type == "var": + var_type = ILVariableSourceType(instr.operands[i] >> 32) + index = instr.operands[i] & 0xffffffff + identifier = instr.operands[i + 1] + i += 1 + value = function.ILVariable(self.function, var_type, index, identifier) + elif operand_type == "int_list": + count = ctypes.c_ulonglong() + operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) + value = [] + for i in xrange(count.value): + value.append(operand_list[i]) + core.BNMediumLevelILFreeOperandList(operand_list) + elif operand_type == "var_ssa_list": + count = ctypes.c_ulonglong() + operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) + i += 1 + value = [] + for j in xrange(count.value / 3): + var_type = ILVariableSourceType(operand_list[j * 3] >> 32) + index = operand_list[j * 3] & 0xffffffff + identifier = operand_list[(j * 3) + 1] + var_index = operand_list[(j * 3) + 2] + value.append((function.ILVariable(self.function, var_type, index, identifier), var_index)) + core.BNMediumLevelILFreeOperandList(operand_list) + self.operands.append(value) + self.__dict__[name] = value + + def __str__(self): + tokens = self.tokens + if tokens is None: + return "invalid" + result = "" + for token in tokens: + result += token.text + return result + + def __repr__(self): + return "" % str(self) + + @property + def tokens(self): + """MLIL tokens (read-only)""" + count = ctypes.c_ulonglong() + tokens = ctypes.POINTER(core.BNInstructionTextToken)() + if (self.instr_index is not None) and (self.function.source_function is not None): + if not core.BNGetMediumLevelILInstructionText(self.function.handle, self.function.source_function.handle, + self.function.arch.handle, self.instr_index, tokens, count): + return None + else: + if not core.BNGetMediumLevelILExprText(self.function.handle, self.function.arch.handle, + self.expr_index, tokens, count): + return None + result = [] + for i in xrange(0, count.value): + token_type = InstructionTextTokenType(tokens[i].type) + text = tokens[i].text + value = tokens[i].value + size = tokens[i].size + operand = tokens[i].operand + context = tokens[i].context + address = tokens[i].address + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + core.BNFreeInstructionText(tokens, count.value) + return result + + @property + def ssa_form(self): + """SSA form of expression (read-only)""" + return MediumLevelILInstruction(self.function.ssa_form, + core.BNGetMediumLevelILSSAExprIndex(self.function.handle, self.expr_index)) + + @property + def non_ssa_form(self): + """Non-SSA form of expression (read-only)""" + return MediumLevelILInstruction(self.function.non_ssa_form, + core.BNGetMediumLevelILNonSSAExprIndex(self.function.handle, self.expr_index)) + + @property + def value(self): + """Value of expression using static data flow analysis (read-only)""" + value = core.BNGetMediumLevelILExprValue(self.function.handle, self.expr_index) + result = function.RegisterValue(self.function.arch, value) + core.BNFreeRegisterValue(value) + return result + + def __setattr__(self, name, value): + try: + object.__setattr__(self, name, value) + except AttributeError: + raise AttributeError("attribute '%s' is read only" % name) + + +class MediumLevelILExpr(object): + """ + ``class MediumLevelILExpr`` hold the index of IL Expressions. + + .. note:: This class shouldn't be instantiated directly. Rather the helper members of MediumLevelILFunction should be \ + used instead. + """ + def __init__(self, index): + self.index = index + + +class MediumLevelILFunction(object): + """ + ``class MediumLevelILFunction`` contains the list of MediumLevelILExpr objects that make up a function. MediumLevelILExpr + objects can be added to the MediumLevelILFunction by calling ``append`` and passing the result of the various class + methods which return MediumLevelILExpr objects. + """ + def __init__(self, arch, handle = None, source_func = None): + self.arch = arch + self.source_function = source_func + 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 + self.handle = core.BNCreateMediumLevelILFunction(arch.handle, func_handle) + + def __del__(self): + core.BNFreeMediumLevelILFunction(self.handle) + + def __eq__(self, value): + if not isinstance(value, MediumLevelILFunction): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, MediumLevelILFunction): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + + @property + def current_address(self): + """Current IL Address (read/write)""" + return core.BNMediumLevelILGetCurrentAddress(self.handle) + + @current_address.setter + def current_address(self, value): + core.BNMediumLevelILSetCurrentAddress(self.handle, self.arch.handle, value) + + def set_current_address(self, value, arch = None): + if arch is None: + arch = self.arch + core.BNMediumLevelILSetCurrentAddress(self.handle, arch.handle, value) + + @property + def basic_blocks(self): + """list of MediumLevelILBasicBlock objects (read-only)""" + count = ctypes.c_ulonglong() + blocks = core.BNGetMediumLevelILBasicBlockList(self.handle, count) + result = [] + view = None + if self.source_function is not None: + view = self.source_function.view + for i in xrange(0, count.value): + result.append(MediumLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self)) + core.BNFreeBasicBlockList(blocks, count.value) + return result + + @property + def ssa_form(self): + """Medium level IL in SSA form (read-only)""" + result = core.BNGetMediumLevelILSSAForm(self.handle) + if not result: + return None + return MediumLevelILFunction(self.arch, result, self.source_function) + + @property + def non_ssa_form(self): + """Medium level IL in non-SSA (default) form (read-only)""" + result = core.BNGetMediumLevelILNonSSAForm(self.handle) + if not result: + return None + return MediumLevelILFunction(self.arch, result, self.source_function) + + def __setattr__(self, name, value): + try: + object.__setattr__(self, name, value) + except AttributeError: + raise AttributeError("attribute '%s' is read only" % name) + + def __len__(self): + return int(core.BNGetMediumLevelILInstructionCount(self.handle)) + + def __getitem__(self, i): + if isinstance(i, slice) or isinstance(i, tuple): + raise IndexError("expected integer instruction index") + if isinstance(i, MediumLevelILExpr): + return MediumLevelILInstruction(self, i.index) + if (i < 0) or (i >= len(self)): + raise IndexError("index out of range") + return MediumLevelILInstruction(self, core.BNGetMediumLevelILIndexForInstruction(self.handle, i), i) + + def __setitem__(self, i, j): + raise IndexError("instruction modification not implemented") + + def __iter__(self): + count = ctypes.c_ulonglong() + blocks = core.BNGetMediumLevelILBasicBlockList(self.handle, count) + view = None + if self.source_function is not None: + view = self.source_function.view + try: + for i in xrange(0, count.value): + yield MediumLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self) + finally: + core.BNFreeBasicBlockList(blocks, count.value) + + def get_instruction_start(self, addr, arch = None): + if arch is None: + arch = self.arch + result = core.BNMediumLevelILGetInstructionStart(self.handle, arch.handle, addr) + if result >= core.BNGetMediumLevelILInstructionCount(self.handle): + return None + return result + + def expr(self, operation, a = 0, b = 0, c = 0, d = 0, e = 0, size = 0): + if isinstance(operation, str): + operation = MediumLevelILOperation[operation] + elif isinstance(operation, MediumLevelILOperation): + operation = operation.value + return MediumLevelILExpr(core.BNMediumLevelILAddExpr(self.handle, operation, size, a, b, c, d, e)) + + def append(self, expr): + """ + ``append`` adds the MediumLevelILExpr ``expr`` to the current MediumLevelILFunction. + + :param MediumLevelILExpr expr: the MediumLevelILExpr to add to the current MediumLevelILFunction + :return: number of MediumLevelILExpr in the current function + :rtype: int + """ + return core.BNMediumLevelILAddInstruction(self.handle, expr.index) + + def goto(self, label): + """ + ``goto`` returns a goto expression which jumps to the provided MediumLevelILLabel. + + :param MediumLevelILLabel label: Label to jump to + :return: the MediumLevelILExpr that jumps to the provided label + :rtype: MediumLevelILExpr + """ + return MediumLevelILExpr(core.BNMediumLevelILGoto(self.handle, label.handle)) + + def if_expr(self, operand, t, f): + """ + ``if_expr`` returns the ``if`` expression which depending on condition ``operand`` jumps to the MediumLevelILLabel + ``t`` when the condition expression ``operand`` is non-zero and ``f`` when it's zero. + + :param MediumLevelILExpr operand: comparison expression to evaluate. + :param MediumLevelILLabel t: Label for the true branch + :param MediumLevelILLabel f: Label for the false branch + :return: the MediumLevelILExpr for the if expression + :rtype: MediumLevelILExpr + """ + return MediumLevelILExpr(core.BNMediumLevelILIf(self.handle, operand.index, t.handle, f.handle)) + + def mark_label(self, label): + """ + ``mark_label`` assigns a MediumLevelILLabel to the current IL address. + + :param MediumLevelILLabel label: + :rtype: None + """ + core.BNMediumLevelILMarkLabel(self.handle, label.handle) + + def add_label_list(self, labels): + """ + ``add_label_list`` returns a label list expression for the given list of MediumLevelILLabel objects. + + :param list(MediumLevelILLabel) lables: the list of MediumLevelILLabel to get a label list expression from + :return: the label list expression + :rtype: MediumLevelILExpr + """ + label_list = (ctypes.POINTER(core.BNMediumLevelILLabel) * len(labels))() + for i in xrange(len(labels)): + label_list[i] = labels[i].handle + return MediumLevelILExpr(core.BNMediumLevelILAddLabelList(self.handle, label_list, len(labels))) + + def add_operand_list(self, operands): + """ + ``add_operand_list`` returns an operand list expression for the given list of integer operands. + + :param list(int) operands: list of operand numbers + :return: an operand list expression + :rtype: MediumLevelILExpr + """ + operand_list = (ctypes.c_ulonglong * len(operands))() + for i in xrange(len(operands)): + operand_list[i] = operands[i] + return MediumLevelILExpr(core.BNMediumLevelILAddOperandList(self.handle, operand_list, len(operands))) + + def operand(self, n, expr): + """ + ``operand`` sets the operand number of the expression ``expr`` and passes back ``expr`` without modification. + + :param int n: + :param MediumLevelILExpr expr: + :return: returns the expression ``expr`` unmodified + :rtype: MediumLevelILExpr + """ + core.BNMediumLevelILSetExprSourceOperand(self.handle, expr.index, n) + return expr + + def finalize(self): + """ + ``finalize`` ends the function and computes the list of basic blocks. + + :rtype: None + """ + core.BNFinalizeMediumLevelILFunction(self.handle) + + def get_ssa_instruction_index(self, instr): + return core.BNGetMediumLevelILSSAInstructionIndex(self.handle, instr) + + def get_non_ssa_instruction_index(self, instr): + return core.BNGetMediumLevelILNonSSAInstructionIndex(self.handle, instr) + + def get_ssa_var_definition(self, var, index): + var_data = core.BNILVariable() + var_data.type = var.type + var_data.index = var.index + var_data.identifier = var.identifier + result = core.BNGetMediumLevelILSSAVarDefinition(self.handle, var_data, index) + if result >= core.BNGetMediumLevelILInstructionCount(self.handle): + return None + return result + + def get_ssa_memory_definition(self, index): + result = core.BNGetMediumLevelILSSAMemoryDefinition(self.handle, index) + if result >= core.BNGetMediumLevelILInstructionCount(self.handle): + return None + return result + + def get_ssa_var_uses(self, var, index): + count = ctypes.c_ulonglong() + var_data = core.BNILVariable() + var_data.type = var.type + var_data.index = var.index + var_data.identifier = var.identifier + instrs = core.BNGetMediumLevelILSSAVarUses(self.handle, var_data, index, count) + result = [] + for i in xrange(0, count.value): + result.append(instrs[i]) + core.BNFreeILInstructionList(instrs) + return result + + def get_ssa_memory_uses(self, index): + count = ctypes.c_ulonglong() + instrs = core.BNGetMediumLevelILSSAMemoryUses(self.handle, index, count) + result = [] + for i in xrange(0, count.value): + result.append(instrs[i]) + core.BNFreeILInstructionList(instrs) + return result + + def get_ssa_var_value(self, var, index): + var_data = core.BNILVariable() + var_data.type = var.type + var_data.index = var.index + var_data.identifier = var.identifier + value = core.BNGetMediumLevelILSSAVarValue(self.handle, var_data, index) + result = function.RegisterValue(self.arch, value) + core.BNFreeRegisterValue(value) + return result + + +class MediumLevelILBasicBlock(basicblock.BasicBlock): + def __init__(self, view, handle, owner): + super(MediumLevelILBasicBlock, self).__init__(view, handle) + self.il_function = owner + + def __iter__(self): + for idx in xrange(self.start, self.end): + yield self.il_function[idx] + + def __getitem__(self, idx): + size = self.end - self.start + if idx > size or idx < -size: + raise IndexError("list index is out of range") + if idx >= 0: + return self.il_function[idx + self.start] + else: + return self.il_function[self.end + idx] -- cgit v1.3.1 From a0132eed82d28d4408a2475847e1804a157b3dc1 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Sat, 4 Mar 2017 18:11:43 -0500 Subject: Adding repo manager APIs --- binaryninjaapi.cpp | 4 + binaryninjaapi.h | 83 +++++++++++ binaryninjacore.h | 117 +++++++++++++++- pluginmanager.cpp | 261 +++++++++++++++++++++++++++++++++++ python/__init__.py | 1 + python/pluginmanager.py | 359 ++++++++++++++++++++++++++++++++++++++++++++++++ python/startup.py | 1 + 7 files changed, 825 insertions(+), 1 deletion(-) create mode 100644 pluginmanager.cpp create mode 100644 python/pluginmanager.py (limited to 'python/__init__.py') diff --git a/binaryninjaapi.cpp b/binaryninjaapi.cpp index e1dab528..1864e389 100644 --- a/binaryninjaapi.cpp +++ b/binaryninjaapi.cpp @@ -41,6 +41,10 @@ void BinaryNinja::InitUserPlugins() BNInitUserPlugins(); } +void BinaryNinja::InitRepoPlugins() +{ + BNInitRepoPlugins(); +} string BinaryNinja::GetBundledPluginDirectory() { diff --git a/binaryninjaapi.h b/binaryninjaapi.h index a918fc42..0ba18f05 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -341,6 +341,7 @@ namespace BinaryNinja void InitCorePlugins(); void InitUserPlugins(); + void InitRepoPlugins(); std::string GetBundledPluginDirectory(); void SetBundledPluginDirectory(const std::string& path); std::string GetUserPluginDirectory(); @@ -2425,4 +2426,86 @@ namespace BinaryNinja virtual BNMessageBoxButtonResult ShowMessageBox(const std::string& title, const std::string& text, BNMessageBoxButtonSet buttons = OKButtonSet, BNMessageBoxIcon icon = InformationIcon) = 0; }; + + typedef BNPluginOrigin PluginOrigin; + typedef BNPluginUpdateStatus PluginUpdateStatus; + typedef BNPluginType PluginType; + typedef BNRepositoryManifest RepositoryManifest; + + class RepoPlugin: public CoreRefCountObject + { + public: + RepoPlugin(const std::string& path, + bool installed, + bool enabled, + const std::string& api, + const std::string& author, + const std::string& description, + const std::string& license, + const std::string& licenseText, + const std::string& longdescription, + const std::string& minimimVersions, + const std::string& name, + const std::vector& pluginTypes, + const std::string& url, + const std::string& version); + RepoPlugin(BNRepoPlugin* plugin); + std::string GetPath() const; + bool IsInstalled() const; + std::string GetPluginDirectory() const; + void SetEnabled(bool enabled); + bool IsEnabled() const; + PluginUpdateStatus GetPluginUpdateStatus() const; + std::string GetApi() const; + std::string GetAuthor() const; + std::string GetDescription() const; + std::string GetLicense() const; + std::string GetLicenseText() const; + std::string GetLongdescription() const; + std::string GetMinimimVersions() const; + std::string GetName() const; + std::vector GetPluginTypes() const; + std::string GetUrl() const; + std::string GetVersion() const; + }; + + class Repository: public CoreRefCountObject + { + public: + Repository(const std::string& url, // URL of the git repository containing the plugins + const std::string& repoPath, // Name of the directory to store this repository within the repositories directory + const std::string& repoManifest="plugins", // Name of the of the inner directory and .json file + const std::string& localReference="master", + const std::string& remoteReference="origin"); + Repository(BNRepository* repository); + ~Repository(); + std::string GetUrl() const; + std::string GetRepoPath() const; + std::string GetLocalReference() const; + std::string GetRemoteReference() const; + std::vector> GetPlugins() const; + bool IsInitialized() const; + std::string GetPluginDirectory() const; + Ref GetPluginByPath(const std::string& pluginPath); + std::string GetFullPath() const; + }; + + class RepositoryManager: public CoreRefCountObject + { + bool m_core; + public: + RepositoryManager(std::vector>& repoInfo, const std::string& enabledPluginsPath); + RepositoryManager(BNRepositoryManager* repoManager); + RepositoryManager(); + ~RepositoryManager(); + bool CheckForUpdates(); + std::vector> GetRepositories(); + Ref GetRepositoryByPath(const std::string& repoName); + bool AddRepository(Ref repo); + bool EnablePlugin(const std::string& repoName, const std::string& pluginPath); + bool DisablePlugin(const std::string& repoName, const std::string& pluginPath); + bool InstallPlugin(const std::string& repoName, const std::string& pluginPath); + bool UninstallPlugin(const std::string& repoName, const std::string& pluginPath); + Ref GetDefaultRepository(); + }; } diff --git a/binaryninjacore.h b/binaryninjacore.h index b2ed7cd3..44ae666b 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -45,6 +45,12 @@ #endif #endif +#ifdef WIN32 +#define PATH_SEP "\\" +#else +#define PATH_SEP "/" +#endif + #define BN_MAX_INSTRUCTION_LENGTH 256 #define BN_DEFAULT_NSTRUCTION_LENGTH 16 #define BN_DEFAULT_OPCODE_DISPLAY 8 @@ -104,6 +110,11 @@ extern "C" struct BNScriptingInstance; struct BNMainThreadAction; struct BNBackgroundTask; + struct BNRepository; + struct BNRepoPlugin; + struct BNRepositoryManager; + + typedef bool (*BNLoadPluginCallback)(const char* repoPath, const char* pluginPath, void* ctx); //! Console log levels enum BNLogLevel @@ -567,6 +578,27 @@ extern "C" ComparisonResultValue }; + enum BNPluginOrigin + { + OfficialPluginOrigin, + CommunityPluginOrigin, + OtherPluginOrigin + }; + + enum BNPluginUpdateStatus + { + UpToDatePluginStatus, + UpdatesAvailablePluginStatus + }; + + enum BNPluginType + { + CorePluginType, + UiPluginType, + ArchitecturePluginType, + BinaryViewPluginType + }; + struct BNLookupTableEntry { int64_t* fromValues; @@ -1187,6 +1219,12 @@ extern "C" uint64_t end; }; + struct BNRepositoryManifest + { + const char* ManifestFile; + const char* RepoDirectory; + }; + BINARYNINJACOREAPI char* BNAllocString(const char* contents); BINARYNINJACOREAPI void BNFreeString(char* str); BINARYNINJACOREAPI void BNFreeStringList(char** strs, size_t count); @@ -1204,10 +1242,13 @@ extern "C" // Plugin initialization BINARYNINJACOREAPI void BNInitCorePlugins(void); BINARYNINJACOREAPI void BNInitUserPlugins(void); + BINARYNINJACOREAPI void BNInitRepoPlugins(void); + BINARYNINJACOREAPI char* BNGetBundledPluginDirectory(void); BINARYNINJACOREAPI void BNSetBundledPluginDirectory(const char* path); BINARYNINJACOREAPI char* BNGetUserPluginDirectory(void); - + BINARYNINJACOREAPI char* BNGetUserDirectory(void); + BINARYNINJACOREAPI char* BNGetRepositoriesDirectory(void); BINARYNINJACOREAPI char* BNGetPathRelativeToBundledPluginDirectory(const char* path); BINARYNINJACOREAPI char* BNGetPathRelativeToUserPluginDirectory(const char* path); @@ -2243,6 +2284,80 @@ extern "C" char*** outVarName, size_t* outVarNameElements); BINARYNINJACOREAPI void BNFreeDemangledName(char*** name, size_t nameElements); + + // Plugin repository APIs + BINARYNINJACOREAPI const char* BNPluginGetApi(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetAuthor(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetDescription(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetLicense(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetLicenseText(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetLongdescription(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetMinimimVersions(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetName(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetUrl(BNRepoPlugin* p); + BINARYNINJACOREAPI const char* BNPluginGetVersion(BNRepoPlugin* p); + BINARYNINJACOREAPI void BNFreePluginTypes(BNPluginType* r); + BINARYNINJACOREAPI BNRepoPlugin* BNCreatePlugin(const char* path, + bool installed, + bool enabled, + const char* api, + const char* author, + const char* description, + const char* license, + const char* licenseText, + const char* longdescription, + const char* minimimVersions, + const char* name, + const BNPluginType* pluginTypes, + size_t pluginTypesSize, + const char* url, + const char* version); + BINARYNINJACOREAPI BNRepoPlugin* BNNewPluginReference(BNRepoPlugin* r); + BINARYNINJACOREAPI void BNFreePlugin(BNRepoPlugin* plugin); + BINARYNINJACOREAPI const char* BNPluginGetPath(BNRepoPlugin* p); + BINARYNINJACOREAPI bool BNPluginIsInstalled(BNRepoPlugin* p); + BINARYNINJACOREAPI void BNPluginSetEnabled(BNRepoPlugin* p, bool enabled); + BINARYNINJACOREAPI bool BNPluginIsEnabled(BNRepoPlugin* p); + BINARYNINJACOREAPI BNPluginUpdateStatus BNPluginGetPluginUpdateStatus(BNRepoPlugin* p); + BINARYNINJACOREAPI BNPluginType* BNPluginGetPluginTypes(BNRepoPlugin* p, size_t* count); + BINARYNINJACOREAPI BNRepository* BNCreateRepository(const char* url, + const char* repoPath, + const char* localReference, + const char* remoteReference); + BINARYNINJACOREAPI BNRepository* BNNewRepositoryReference(BNRepository* r); + BINARYNINJACOREAPI void BNFreeRepository(BNRepository* r); + BINARYNINJACOREAPI char* BNRepositoryGetUrl(BNRepository* r); + BINARYNINJACOREAPI char* BNRepositoryGetRepoPath(BNRepository* r); + BINARYNINJACOREAPI char* BNRepositoryGetLocalReference(BNRepository* r); + BINARYNINJACOREAPI char* BNRepositoryGetRemoteReference(BNRepository* r); + BINARYNINJACOREAPI BNRepoPlugin** BNRepositoryGetPlugins(BNRepository* r, size_t* count); + BINARYNINJACOREAPI void BNFreeRepositoryPluginList(BNRepoPlugin** r); + BINARYNINJACOREAPI bool BNRepositoryIsInitialized(BNRepository* r); + BINARYNINJACOREAPI void BNRepositoryFreePluginDirectoryList(char** list, size_t count); + BINARYNINJACOREAPI BNRepoPlugin* BNRepositoryGetPluginByPath(BNRepository* r, const char* pluginPath); + BINARYNINJACOREAPI const char* BNRepositoryGetPluginsPath(BNRepository* r); + + BINARYNINJACOREAPI BNRepositoryManager* BNCreateRepositoryManager(BNRepository** repos, + size_t reposSize, + const char* enabledPluginsPath); + BINARYNINJACOREAPI BNRepositoryManager* BNNewRepositoryManagerReference(BNRepositoryManager* r); + BINARYNINJACOREAPI void BNFreeRepositoryManager(BNRepositoryManager* r); + BINARYNINJACOREAPI bool BNRepositoryManagerCheckForUpdates(BNRepositoryManager* r); + BINARYNINJACOREAPI BNRepository** BNRepositoryManagerGetRepositories(BNRepositoryManager* r, size_t* count); + BINARYNINJACOREAPI void BNFreeRepositoryManagerRepositoriesList(BNRepository** r); + BINARYNINJACOREAPI bool BNRepositoryManagerAddRepository(BNRepositoryManager* r, BNRepository* repo); + BINARYNINJACOREAPI bool BNRepositoryManagerEnablePlugin(BNRepositoryManager* r, const char* repoName, const char* pluginPath); + BINARYNINJACOREAPI bool BNRepositoryManagerDisablePlugin(BNRepositoryManager* r, const char* repoName, const char* pluginPath); + BINARYNINJACOREAPI bool BNRepositoryManagerInstallPlugin(BNRepositoryManager* r, const char* repoName, const char* pluginPath); + BINARYNINJACOREAPI bool BNRepositoryManagerUninstallPlugin(BNRepositoryManager* r, const char* repoName, const char* pluginPath); + BINARYNINJACOREAPI bool BNRepositoryManagerUpdatePlugin(BNRepositoryManager* r, const char* repoName, const char* pluginPath); + BINARYNINJACOREAPI BNRepository* BNRepositoryGetRepositoryByPath(BNRepositoryManager* r, const char* repoPath); + BINARYNINJACOREAPI BNRepositoryManager* BNGetRepositoryManager(); + + BINARYNINJACOREAPI BNRepository* BNRepositoryManagerGetDefaultRepository(BNRepositoryManager* r); + BINARYNINJACOREAPI void BNRegisterForPluginLoading(const char* pluginApiName, BNLoadPluginCallback cb, void* ctx); + BINARYNINJACOREAPI bool BNLoadPluginForApi(const char* pluginApiName, const char* repoPath, const char* pluginPath); + #ifdef __cplusplus } #endif diff --git a/pluginmanager.cpp b/pluginmanager.cpp new file mode 100644 index 00000000..24f6f09f --- /dev/null +++ b/pluginmanager.cpp @@ -0,0 +1,261 @@ +#include "binaryninjaapi.h" + +using namespace BinaryNinja; +using namespace std; + +#define RETURN_STRING(s) do { \ + char* contents = (char*)(s); \ + string result(contents); \ + BNFreeString(contents); \ + return result; \ +}while(0) + +RepoPlugin::RepoPlugin(const string& path, + bool installed, + bool enabled, + const string& api, + const string& author, + const string& description, + const string& license, + const string& licenseText, + const string& longdescription, + const string& minimimVersions, + const string& name, + const vector& pluginTypes, + const string& url, + const string& version) +{ + m_object = BNCreatePlugin(path.c_str(), + installed, + enabled, + api.c_str(), + author.c_str(), + description.c_str(), + license.c_str(), + licenseText.c_str(), + longdescription.c_str(), + minimimVersions.c_str(), + name.c_str(), + &pluginTypes[0], + pluginTypes.size(), + url.c_str(), + version.c_str()); +} + +RepoPlugin::RepoPlugin(BNRepoPlugin* plugin) +{ + m_object = plugin; +} + +string RepoPlugin::GetPath() const +{ + RETURN_STRING(BNPluginGetPath(m_object)); +} + +bool RepoPlugin::IsInstalled() const +{ + return BNPluginIsInstalled(m_object); +} + +void RepoPlugin::SetEnabled(bool enabled) +{ + return BNPluginSetEnabled(m_object, enabled); +} + +bool RepoPlugin::IsEnabled() const +{ + return BNPluginIsEnabled(m_object); +} + +PluginUpdateStatus RepoPlugin::GetPluginUpdateStatus() const +{ + return BNPluginGetPluginUpdateStatus(m_object); +} + +string RepoPlugin::GetApi() const +{ + RETURN_STRING(BNPluginGetApi(m_object)); +} + +string RepoPlugin::GetAuthor() const +{ + RETURN_STRING(BNPluginGetAuthor(m_object)); +} + +string RepoPlugin::GetDescription() const +{ + RETURN_STRING(BNPluginGetDescription(m_object)); +} + +string RepoPlugin::GetLicense() const +{ + RETURN_STRING(BNPluginGetLicense(m_object)); +} + +string RepoPlugin::GetLicenseText() const +{ + RETURN_STRING(BNPluginGetLicenseText(m_object)); +} + +string RepoPlugin::GetLongdescription() const +{ + RETURN_STRING(BNPluginGetLongdescription(m_object)); +} + +string RepoPlugin::GetMinimimVersions() const +{ + RETURN_STRING(BNPluginGetMinimimVersions(m_object)); +} + +string RepoPlugin::GetName() const +{ + RETURN_STRING(BNPluginGetName(m_object)); +} + +vector RepoPlugin::GetPluginTypes() const +{ + size_t count; + BNPluginType* pluginTypesPtr = BNPluginGetPluginTypes(m_object, &count); + vector pluginTypes; + for (size_t i = 0; i < count; i++) + { + pluginTypes.push_back((PluginType)pluginTypesPtr[i]); + } + BNFreePluginTypes(pluginTypesPtr); + return pluginTypes; +} + +string RepoPlugin::GetUrl() const +{ + RETURN_STRING(BNPluginGetUrl(m_object)); +} + +string RepoPlugin::GetVersion() const +{ + RETURN_STRING(BNPluginGetVersion(m_object)); +} + +Repository::Repository(const string& url, + const string& repoPath, + const string& repoManifest, + const string& localReference, + const string& remoteReference) +{ + m_object = BNCreateRepository(url.c_str(), + repoPath.c_str(), + localReference.c_str(), + remoteReference.c_str()); +} + +Repository::Repository(BNRepository* r) +{ + m_object = r; +} + +Repository::~Repository() +{ + BNFreeRepository(m_object); +} +string Repository::GetUrl() const +{ + RETURN_STRING(BNRepositoryGetUrl(m_object)); +} +string Repository::GetRepoPath() const +{ + RETURN_STRING(BNRepositoryGetRepoPath(m_object)); +} + +string Repository::GetLocalReference() const +{ + RETURN_STRING(BNRepositoryGetLocalReference(m_object)); +} + +string Repository::GetRemoteReference() const +{ + RETURN_STRING(BNRepositoryGetRemoteReference(m_object)); +} + +vector> Repository::GetPlugins() const +{ + vector> plugins; + size_t count = 0; + BNRepoPlugin** pluginsPtr = BNRepositoryGetPlugins(m_object, &count); + for (size_t i = 0; i < count; i++) + plugins.push_back(new RepoPlugin(BNNewPluginReference(pluginsPtr[i]))); + BNFreeRepositoryPluginList(pluginsPtr); + return plugins; +} + +bool Repository::IsInitialized() const +{ + return BNRepositoryIsInitialized(m_object); +} + +Ref Repository::GetPluginByPath(const string& pluginPath) +{ + return new RepoPlugin(BNNewPluginReference(BNRepositoryGetPluginByPath(m_object, pluginPath.c_str()))); +} + +string Repository::GetFullPath() const +{ + RETURN_STRING(BNRepositoryGetPluginsPath(m_object)); +} + +RepositoryManager::RepositoryManager(vector>& repoInfo, const string& enabledPluginsPath) + :m_core(false) +{ + BNRepository** buffer = new BNRepository*[repoInfo.size()]; + for (size_t i = 0; i < repoInfo.size(); i++) + buffer[i] = repoInfo[i]->m_object; + m_object = BNCreateRepositoryManager(buffer, repoInfo.size(), enabledPluginsPath.c_str()); + delete[] buffer; +} + +RepositoryManager::RepositoryManager(BNRepositoryManager* mgr) + :m_core(false) +{ + m_object = mgr; +} + +RepositoryManager::RepositoryManager() + :m_core(true) +{ + m_object = BNGetRepositoryManager(); +} + +RepositoryManager::~RepositoryManager() +{ + if (!m_core) + BNFreeRepositoryManager(m_object); +} + +bool RepositoryManager::CheckForUpdates() +{ + return BNRepositoryManagerCheckForUpdates(m_object); +} + +vector> RepositoryManager::GetRepositories() +{ + vector> repos; + size_t count = 0; + BNRepository** reposPtr = BNRepositoryManagerGetRepositories(m_object, &count); + for (size_t i = 0; i < count; i++) + repos.push_back(new Repository(BNNewRepositoryReference(reposPtr[i]))); + BNFreeRepositoryManagerRepositoriesList(reposPtr); + return repos; +} + +bool RepositoryManager::AddRepository(Ref repo) +{ + return BNRepositoryManagerAddRepository(m_object, repo->GetObject()); +} + +Ref RepositoryManager::GetRepositoryByPath(const std::string& repoPath) +{ + return new Repository(BNNewRepositoryReference(BNRepositoryGetRepositoryByPath(m_object, repoPath.c_str()))); +} + +Ref RepositoryManager::GetDefaultRepository() +{ + return new Repository(BNNewRepositoryReference(BNRepositoryManagerGetDefaultRepository(m_object))); +} diff --git a/python/__init__.py b/python/__init__.py index a1ea02f5..5df7c7f1 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -45,6 +45,7 @@ from .lineardisassembly import * from .undoaction import * from .highlight import * from .scriptingprovider import * +from .pluginmanager import * def shutdown(): diff --git a/python/pluginmanager.py b/python/pluginmanager.py new file mode 100644 index 00000000..348f13fb --- /dev/null +++ b/python/pluginmanager.py @@ -0,0 +1,359 @@ +# Copyright (c) 2015-2016 Vector 35 LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import ctypes + +# Binary Ninja components +import _binaryninjacore as core +from .enums import PluginType, PluginUpdateStatus +import startup + + +class RepoPlugin(object): + """ + ``Plugin`` is a read-only class. Use RepositoryManager to Enable/Disable/Install/Uninstall plugins. + """ + def __init__(self, handle): + self.handle = core.handle_of_type(handle, core.BNRepoPlugin) + + def __del__(self): + core.BNFreePlugin(self.handle) + + def __repr__(self): + return "<{} {}/{}>".format(self.path, "installed" if self.installed else "not-installed", "enabled" if self.enabled else "disabled") + + @property + def path(self): + """Relative path from the base of the repository to the actual plugin""" + return core.BNPluginGetPath(self.handle) + + @property + def installed(self): + """Boolean True if the plugin is installed, False otherwise""" + return core.BNPluginIsInstalled(self.handle) + + @property + def enabled(self): + """Boolean True if the plugin is currently enabled, False otherwise""" + return core.BNPluginIsEnabled(self.handle) + + @property + def api(self): + """string indicating the api used by the plugin""" + return core.BNPluginGetApi(self.handle) + + @property + def description(self): + """String short description of the plugin""" + return core.BNPluginGetDescription(self.handle) + + @property + def license(self): + """String short license description (ie MIT, BSD, GPLv2, etc)""" + return core.BNPluginGetLicense(self.handle) + + @property + def license_text(self): + """String complete license text for the given plugin""" + return core.BNPluginGetLicenseText(self.handle) + + @property + def long_description(self): + """String long description of the plugin""" + return core.BNPluginGetLongdescription(self.handle) + + @property + def minimum_version(self): + """String minimum version the plugin was tested on""" + return core.BNPluginGetMinimimVersions(self.handle) + + @property + def name(self): + """String name of the plugin""" + return core.BNPluginGetName(self.handle) + + @property + def plugin_types(self): + """List of PluginType enumeration objects indicating the plugin type(s)""" + result = [] + count = ctypes.c_ulonglong(0) + plugintypes = core.BNPluginGetPluginTypes(self.handle, count) + for i in xrange(count.value): + result.append(PluginType(plugintypes[i])) + core.BNFreePluginTypes(plugintypes) + return result + + @property + def url(self): + """String url of the plugin's git repository""" + return core.BNPluginGetUrl(self.handle) + + @property + def version(self): + """String version of the plugin""" + return core.BNPluginGetVersion(self.handle) + + @property + def update_status(self): + """PluginUpdateStatus enumeration indicating if the plugin is up to date or not""" + return PluginUpdateStatus(core.BNPluginGetPluginUpdateStatus(self.handle)) + + +class Repository(object): + """ + ``Repository`` is a read-only class. Use RepositoryManager to Enable/Disable/Install/Uninstall plugins. + """ + def __init__(self, handle): + self.handle = core.handle_of_type(handle, core.BNRepository) + + def __del__(self): + core.BNFreeRepository(self.handle) + + def __repr__(self): + return "<{} - {}/{}>".format(self.path, self.remote_reference, self.local_reference) + + @property + def url(self): + """String url of the git repository where the plugin repository's are stored""" + return core.BNRepositoryGetUrl(self.handle) + + @property + def path(self): + """String local path to store the given plugin repository""" + return core.BNRepositoryGetRepoPath(self.handle) + + @property + def local_reference(self): + """String for the local git reference (ie 'master')""" + return core.BNRepositoryGetLocalReference(self.handle) + + @property + def remote_reference(self): + """String for the remote git reference (ie 'origin')""" + return core.BNRepositoryGetRemoteReference(self.handle) + + @property + def plugins(self): + """List of Plugin objects contained within this repository""" + pluginlist = [] + count = ctypes.c_ulonglong(0) + result = core.BNRepositoryGetPlugins(self.handle, count) + for i in xrange(count.value): + pluginlist.append(RepoPlugin(handle=result[i])) + core.BNFreeRepositoryPluginList(result, count.value) + del result + return pluginlist + + @property + def initialized(self): + """Boolean True when the repository has been initialized""" + return core.BNRepositoryIsInitialized(self.handle) + + +class RepositoryManager(object): + def __init__(self, handle=None): + self.handle = core.BNGetRepositoryManager() + + def check_for_updates(self): + """Check for updates for all managed Repository objects""" + return core.BNRepositoryManagerCheckForUpdates(self.handle) + + @property + def repositories(self): + """List of Repository objects being managed""" + result = [] + count = ctypes.c_ulonglong(0) + repos = core.BNRepositoryManagerGetRepositories(self.handle, count) + for i in xrange(count.value): + result.append(Repository(handle=repos[i])) + core.BNFreeRepositoryManagerRepositoriesList(repos) + return result + + @property + def plugins(self): + """List of all RepoPlugins in each repository""" + plgs = {} + for repo in self.repositories: + plgs[repo.path] = repo.plugins + return plgs + + @property + def default_repository(self): + """Gets the default Repository""" + startup._init_plugins() + return Repository(handle=core.BNRepositoryManagerGetDefaultRepository(self.handle)) + + def enable_plugin(self, plugin, install=True, repo=None): + """ + ``enable_plugin`` Enables the installed plugin 'plugin', optionally installing the plugin if `install` is set to + True (default), and optionally using the non-default repository. + + :param str name: Name of the plugin to enable + :param Boolean install: Optionally install the repo, defaults to True. + :param str repo: Optional, specify a repository other than the default repository. + :return: Boolean value True if the plugin was successfully enabled, False otherwise + :rtype: Boolean + :Example: + + >>> mgr = RepositoryManager() + >>> mgr.enable_plugin('binaryninja-bookmarks') + True + >>> + """ + if install: + if not self.install_plugin(plugin, repo): + return False + + if repo is None: + repo = self.default_repository + repopath = repo + pluginpath = plugin + if not isinstance(repo, str): + repopath = repo.path + if not isinstance(plugin, str): + pluginpath = plugin.path + return core.BNRepositoryManagerEnablePlugin(self.handle, repopath, pluginpath) + + def disable_plugin(self, plugin, repo=None): + """ + ``disable_plugin`` Disable the specified plugin, pluginpath + + :param Repository or str repo: Repository containing the plugin to disable + :param Plugin or str plugin: Plugin to disable + :return: Boolean value True if the plugin was successfully disabled, False otherwise + :rtype: Boolean + :Example: + + >>> mgr = RepositoryManager() + >>> mgr.disable_plugin('binaryninja-bookmarks') + True + >>> + """ + if repo is None: + repo = self.default_repository + repopath = repo + pluginpath = plugin + if not isinstance(repo, str): + repopath = repo.path + if not isinstance(plugin, str): + pluginpath = plugin.path + return core.BNRepositoryManagerDisablePlugin(self.handle, repopath, pluginpath) + + def install_plugin(self, plugin, repo=None): + """ + ``install_plugin`` install the specified plugin, pluginpath + + :param Repository or str repo: Repository containing the plugin to install + :param Plugin or str plugin: Plugin to install + :return: Boolean value True if the plugin was successfully installed, False otherwise + :rtype: Boolean + :Example: + + >>> mgr = RepositoryManager() + >>> mgr.install_plugin('binaryninja-bookmarks') + True + >>> + """ + if repo is None: + repo = self.default_repository + repopath = repo + pluginpath = plugin + if not isinstance(repo, str): + repopath = repo.path + if not isinstance(plugin, str): + pluginpath = plugin.path + return core.BNRepositoryManagerInstallPlugin(self.handle, repopath, pluginpath) + + def uninstall_plugin(self, plugin, repo=None): + """ + ``uninstall_plugin`` uninstall the specified plugin, pluginpath + + :param Repository or str repo: Repository containing the plugin to uninstall + :param Plugin or str plugin: Plugin to uninstall + :return: Boolean value True if the plugin was successfully uninstalled, False otherwise + :rtype: Boolean + :Example: + + >>> mgr = RepositoryManager() + >>> mgr.uninstall_plugin('binaryninja-bookmarks') + True + >>> + """ + if repo is None: + repo = self.default_repository + repopath = repo + pluginpath = plugin + if not isinstance(repo, str): + repopath = repo.path + if not isinstance(plugin, str): + pluginpath = plugin.path + return core.BNRepositoryManagerUninstallPlugin(self.handle, repopath, pluginpath) + + def update_plugin(self, plugin, repo=None): + """ + ``update_plugin`` update the specified plugin, pluginpath + + :param Repository or str repo: Repository containing the plugin to update + :param Plugin or str plugin: Plugin to update + :return: Boolean value True if the plugin was successfully updated, False otherwise + :rtype: Boolean + :Example: + + >>> mgr = RepositoryManager() + >>> mgr.update_plugin('binaryninja-bookmarks') + True + >>> + """ + if repo is None: + repo = self.default_repository + repopath = repo + pluginpath = plugin + if not isinstance(repo, str): + repopath = repo.path + if not isinstance(plugin, str): + pluginpath = plugin.path + return core.BNRepositoryManagerUpdatePlugin(self.handle, repopath, pluginpath) + + def add_repository(self, url=None, repopath=None, localreference="master", remotereference="origin"): + """ + ``add_repository`` adds a new plugin repository for the manager to track. + + :param str url: Url to the git repository where the plugins are stored. + :param str repopath: path to where the repository will be stored on disk locally + :param str localreference: Optional reference to the local tracking branch typically "master" + :param str remotereference: Optional reference to the remote tracking branch typically "origin" + :return: Boolean value True if the repository was successfully added, False otherwise. + :rtype: Boolean + :Example: + + >>> mgr = RepositoryManager() + >>> mgr.add_repository(url="https://github.com/vector35/binaryninja-plugins.git", + repopath="myrepo", + repomanifest="plugins", + localreference="master", remotereference="origin") + True + >>> + """ + if not (isinstance(url, str) and isinstance(repopath, str) and + isinstance(localreference, str) and isinstance(remotereference, str)): + raise ValueError("Parameter is incorrect type") + repo = core.BNCreateRepository(url, repopath, localreference, remotereference) + + return core.BNRepositoryManagerAddRepository(self.handle, repo) diff --git a/python/startup.py b/python/startup.py index 809f185b..324cc690 100644 --- a/python/startup.py +++ b/python/startup.py @@ -30,5 +30,6 @@ def _init_plugins(): _plugin_init = True core.BNInitCorePlugins() core.BNInitUserPlugins() + core.BNInitRepoPlugins() if not core.BNIsLicenseValidated(): raise RuntimeError("License is not valid. Please supply a valid license.") -- cgit v1.3.1 From aac1ebc6c004fc908c72d7dbee96d48d79440df4 Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Fri, 19 May 2017 12:08:21 -0400 Subject: update copyright year --- LICENSE.txt | 2 +- architecture.cpp | 2 +- basicblock.cpp | 2 +- binaryninjaapi.cpp | 2 +- binaryninjaapi.h | 2 +- binaryninjacore.h | 2 +- binaryreader.cpp | 2 +- binaryview.cpp | 2 +- binaryviewtype.cpp | 2 +- binarywriter.cpp | 2 +- callingconvention.cpp | 2 +- databuffer.cpp | 2 +- fileaccessor.cpp | 2 +- filemetadata.cpp | 2 +- function.cpp | 2 +- functiongraph.cpp | 2 +- functiongraphblock.cpp | 2 +- functionrecognizer.cpp | 2 +- log.cpp | 2 +- lowlevelil.cpp | 2 +- platform.cpp | 2 +- plugin.cpp | 2 +- python/__init__.py | 2 +- python/architecture.py | 2 +- python/associateddatastore.py | 2 +- python/basicblock.py | 2 +- python/binaryview.py | 2 +- python/callingconvention.py | 2 +- python/databuffer.py | 2 +- python/demangle.py | 2 +- python/examples/angr_plugin.py | 2 +- python/examples/bin_info.py | 2 +- python/examples/breakpoint.py | 2 +- python/examples/instruction_iterator.py | 2 +- python/examples/jump_table.py | 2 +- python/examples/nds.py | 2 +- python/examples/nes.py | 2 +- python/examples/nsf.py | 2 +- python/examples/print_syscalls.py | 2 +- python/examples/version_switcher.py | 2 +- python/fileaccessor.py | 2 +- python/filemetadata.py | 2 +- python/function.py | 2 +- python/functionrecognizer.py | 2 +- python/generator.cpp | 2 +- python/highlight.py | 2 +- python/interaction.py | 2 +- python/lineardisassembly.py | 2 +- python/log.py | 2 +- python/lowlevelil.py | 2 +- python/mainthread.py | 2 +- python/platform.py | 2 +- python/plugin.py | 2 +- python/pluginmanager.py | 2 +- python/scriptingprovider.py | 2 +- python/startup.py | 2 +- python/transform.py | 2 +- python/types.py | 2 +- python/undoaction.py | 2 +- python/update.py | 2 +- tempfile.cpp | 2 +- transform.cpp | 2 +- type.cpp | 2 +- update.cpp | 2 +- 64 files changed, 64 insertions(+), 64 deletions(-) (limited to 'python/__init__.py') diff --git a/LICENSE.txt b/LICENSE.txt index 625bc6c9..ef8398a2 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2015-2016 Vector 35 LLC +Copyright (c) 2015-2017 Vector 35 LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to diff --git a/architecture.cpp b/architecture.cpp index 02f2a88f..eb70b16c 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/basicblock.cpp b/basicblock.cpp index d8ae0f65..7eb37c57 100644 --- a/basicblock.cpp +++ b/basicblock.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/binaryninjaapi.cpp b/binaryninjaapi.cpp index 661892e3..c425df88 100644 --- a/binaryninjaapi.cpp +++ b/binaryninjaapi.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 783f6345..d27ab5fa 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/binaryninjacore.h b/binaryninjacore.h index dbd78f8b..23014782 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/binaryreader.cpp b/binaryreader.cpp index 5c8a0dc6..ad4859ff 100644 --- a/binaryreader.cpp +++ b/binaryreader.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/binaryview.cpp b/binaryview.cpp index 8edbc2bf..b18b065b 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/binaryviewtype.cpp b/binaryviewtype.cpp index e7feb68c..e23838f6 100644 --- a/binaryviewtype.cpp +++ b/binaryviewtype.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/binarywriter.cpp b/binarywriter.cpp index efac9d9e..a7426346 100644 --- a/binarywriter.cpp +++ b/binarywriter.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/callingconvention.cpp b/callingconvention.cpp index 770daf78..fb5ed73f 100644 --- a/callingconvention.cpp +++ b/callingconvention.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/databuffer.cpp b/databuffer.cpp index 72788e8c..f2031842 100644 --- a/databuffer.cpp +++ b/databuffer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/fileaccessor.cpp b/fileaccessor.cpp index 1fa69746..29fb45ae 100644 --- a/fileaccessor.cpp +++ b/fileaccessor.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/filemetadata.cpp b/filemetadata.cpp index b3764167..dc08fe30 100644 --- a/filemetadata.cpp +++ b/filemetadata.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/function.cpp b/function.cpp index 194153a8..b570499c 100644 --- a/function.cpp +++ b/function.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/functiongraph.cpp b/functiongraph.cpp index 30e2e165..7e5ec079 100644 --- a/functiongraph.cpp +++ b/functiongraph.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/functiongraphblock.cpp b/functiongraphblock.cpp index a37c0b49..99ce2e08 100644 --- a/functiongraphblock.cpp +++ b/functiongraphblock.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/functionrecognizer.cpp b/functionrecognizer.cpp index 45e19faf..32c7245c 100644 --- a/functionrecognizer.cpp +++ b/functionrecognizer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/log.cpp b/log.cpp index edeed17d..dd15559f 100644 --- a/log.cpp +++ b/log.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 178d3709..c48b5b92 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/platform.cpp b/platform.cpp index afbcbbf3..2a095da2 100644 --- a/platform.cpp +++ b/platform.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/plugin.cpp b/plugin.cpp index 9f51e989..e8dd881d 100644 --- a/plugin.cpp +++ b/plugin.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/python/__init__.py b/python/__init__.py index c7c5f768..4f58a6db 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/architecture.py b/python/architecture.py index 236ef90b..34f2ca35 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/associateddatastore.py b/python/associateddatastore.py index 6b5e688e..c9b35ee0 100644 --- a/python/associateddatastore.py +++ b/python/associateddatastore.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/basicblock.py b/python/basicblock.py index 5bec391b..3dc5b050 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/binaryview.py b/python/binaryview.py index 09537a16..5a03b800 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/callingconvention.py b/python/callingconvention.py index 04ba711f..4c87eef6 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/databuffer.py b/python/databuffer.py index 6b3423da..3f9e4ce5 100644 --- a/python/databuffer.py +++ b/python/databuffer.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/demangle.py b/python/demangle.py index 2a17cdfd..11673263 100644 --- a/python/demangle.py +++ b/python/demangle.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/angr_plugin.py b/python/examples/angr_plugin.py index 90217d65..c84373be 100644 --- a/python/examples/angr_plugin.py +++ b/python/examples/angr_plugin.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/bin_info.py b/python/examples/bin_info.py index 495fb5b5..17a96685 100644 --- a/python/examples/bin_info.py +++ b/python/examples/bin_info.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/breakpoint.py b/python/examples/breakpoint.py index b1297e26..a2801511 100644 --- a/python/examples/breakpoint.py +++ b/python/examples/breakpoint.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/instruction_iterator.py b/python/examples/instruction_iterator.py index 7ff2d692..f55e1c1b 100644 --- a/python/examples/instruction_iterator.py +++ b/python/examples/instruction_iterator.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/jump_table.py b/python/examples/jump_table.py index 439e2ab6..419cc188 100644 --- a/python/examples/jump_table.py +++ b/python/examples/jump_table.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/nds.py b/python/examples/nds.py index ff137b4b..34d8a292 100644 --- a/python/examples/nds.py +++ b/python/examples/nds.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/nes.py b/python/examples/nes.py index 47f98b43..e55a90b7 100644 --- a/python/examples/nes.py +++ b/python/examples/nes.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/nsf.py b/python/examples/nsf.py index b1bac3a8..b0164065 100644 --- a/python/examples/nsf.py +++ b/python/examples/nsf.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/print_syscalls.py b/python/examples/print_syscalls.py index 2af4d38d..d995ad1e 100644 --- a/python/examples/print_syscalls.py +++ b/python/examples/print_syscalls.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/examples/version_switcher.py b/python/examples/version_switcher.py index 9d5bbf05..3e1cab40 100644 --- a/python/examples/version_switcher.py +++ b/python/examples/version_switcher.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/fileaccessor.py b/python/fileaccessor.py index 8fec43a1..2c1f1d19 100644 --- a/python/fileaccessor.py +++ b/python/fileaccessor.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/filemetadata.py b/python/filemetadata.py index b489d5bb..4bfc0214 100644 --- a/python/filemetadata.py +++ b/python/filemetadata.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/function.py b/python/function.py index f32f6ad6..0352ee58 100644 --- a/python/function.py +++ b/python/function.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/functionrecognizer.py b/python/functionrecognizer.py index 960aee2f..8514a2ee 100644 --- a/python/functionrecognizer.py +++ b/python/functionrecognizer.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/generator.cpp b/python/generator.cpp index 1c0e7b16..6f19db66 100644 --- a/python/generator.cpp +++ b/python/generator.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/python/highlight.py b/python/highlight.py index 6af1cf95..96bc543d 100644 --- a/python/highlight.py +++ b/python/highlight.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/interaction.py b/python/interaction.py index b479e922..60607692 100644 --- a/python/interaction.py +++ b/python/interaction.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/lineardisassembly.py b/python/lineardisassembly.py index 9b88b78a..5ef8d623 100644 --- a/python/lineardisassembly.py +++ b/python/lineardisassembly.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/log.py b/python/log.py index 850772f1..f7144183 100644 --- a/python/log.py +++ b/python/log.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 5b133abd..d1a76a2a 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/mainthread.py b/python/mainthread.py index 220f0b64..3e12bd65 100644 --- a/python/mainthread.py +++ b/python/mainthread.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/platform.py b/python/platform.py index 139b7d5e..9ba7625f 100644 --- a/python/platform.py +++ b/python/platform.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/plugin.py b/python/plugin.py index 2632b5a9..f038d122 100644 --- a/python/plugin.py +++ b/python/plugin.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/pluginmanager.py b/python/pluginmanager.py index 37962114..c0f70260 100644 --- a/python/pluginmanager.py +++ b/python/pluginmanager.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index 859f262e..94616d59 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/startup.py b/python/startup.py index 324cc690..0abc47cb 100644 --- a/python/startup.py +++ b/python/startup.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/transform.py b/python/transform.py index 40382c69..59d719e7 100644 --- a/python/transform.py +++ b/python/transform.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/types.py b/python/types.py index ebaa36fc..1e566f68 100644 --- a/python/types.py +++ b/python/types.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/undoaction.py b/python/undoaction.py index 9f742e00..7e3c76a0 100644 --- a/python/undoaction.py +++ b/python/undoaction.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/python/update.py b/python/update.py index 6417e4a0..be6962d7 100644 --- a/python/update.py +++ b/python/update.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# Copyright (c) 2015-2017 Vector 35 LLC # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/tempfile.cpp b/tempfile.cpp index 4683bbcd..a8ee32d4 100644 --- a/tempfile.cpp +++ b/tempfile.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/transform.cpp b/transform.cpp index d7ec44b9..29a665d0 100644 --- a/transform.cpp +++ b/transform.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/type.cpp b/type.cpp index 32da27d2..5dd00cbd 100644 --- a/type.cpp +++ b/type.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to diff --git a/update.cpp b/update.cpp index 9d9a2216..135fee5e 100644 --- a/update.cpp +++ b/update.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// Copyright (c) 2015-2017 Vector 35 LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to -- cgit v1.3.1