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