diff options
| author | Rusty Wagner <rusty@vector35.com> | 2017-01-11 15:42:08 -0500 |
|---|---|---|
| committer | Rusty Wagner <rusty@vector35.com> | 2017-01-11 15:42:08 -0500 |
| commit | 09a68bdd84d4789626f5c8b8631f61e7a41ca03d (patch) | |
| tree | 5d294b337d32e4b573c259539417987be125de9b | |
| parent | d9455e8b6319ccb766a3a9f274244a54d159e7f4 (diff) | |
Use named type references for registered types, use qualified names for types
| -rw-r--r-- | architecture.cpp | 57 | ||||
| -rw-r--r-- | binaryninjaapi.h | 62 | ||||
| -rw-r--r-- | binaryninjacore.h | 71 | ||||
| -rw-r--r-- | binaryview.cpp | 134 | ||||
| -rw-r--r-- | python/__init__.py | 290 | ||||
| -rw-r--r-- | python/generator.cpp | 46 | ||||
| -rw-r--r-- | type.cpp | 111 |
7 files changed, 533 insertions, 238 deletions
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<string, Ref<Type>>& types, map<string, Ref<Type>>& variables, - map<string, Ref<Type>>& functions, string& errors, - const vector<string>& includeDirs) + map<vector<string>, Ref<Type>>& types, map<vector<string>, Ref<Type>>& variables, + map<vector<string>, Ref<Type>>& functions, string& errors, const vector<string>& 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<string> 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<string> 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<string> 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<string, Ref<Type>>& types, - map<string, Ref<Type>>& variables, map<string, Ref<Type>>& functions, - string& errors, const vector<string>& includeDirs) +bool Architecture::ParseTypesFromSourceFile(const string& fileName, map<vector<string>, Ref<Type>>& types, + map<vector<string>, Ref<Type>>& variables, map<vector<string>, Ref<Type>>& functions, + string& errors, const vector<string>& includeDirs) { BNTypeParserResult result; char* errorStr; @@ -795,18 +809,33 @@ bool Architecture::ParseTypesFromSourceFile(const string& fileName, map<string, functions.clear(); bool ok = BNParseTypesFromSourceFile(m_object, fileName.c_str(), &result, &errorStr, - includeDirList, includeDirs.size()); + 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<string> 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<string> 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<string> 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<std::string>& name, Type* type) { (void)data; (void)name; (void)type; } + virtual void OnTypeUndefined(BinaryView* data, const std::vector<std::string>& 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<LinearDisassemblyLine> 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<std::string, Ref<Type>> GetTypes(); + std::map<std::vector<std::string>, Ref<Type>> GetTypes(); Ref<Type> GetTypeByName(const std::string& name); + Ref<Type> GetTypeByName(const std::vector<std::string>& name); bool IsTypeAutoDefined(const std::string& name); + bool IsTypeAutoDefined(const std::vector<std::string>& name); void DefineType(const std::string& name, Ref<Type> type); + void DefineType(const std::vector<std::string>& name, Ref<Type> type); void DefineUserType(const std::string& name, Ref<Type> type); + void DefineUserType(const std::vector<std::string>& name, Ref<Type> type); void UndefineType(const std::string& name); + void UndefineType(const std::vector<std::string>& name); void UndefineUserType(const std::string& name); + void UndefineUserType(const std::vector<std::string>& 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<std::string, Ref<Type>>& types, std::map<std::string, Ref<Type>>& variables, - std::map<std::string, Ref<Type>>& functions, std::string& errors, - const std::vector<std::string>& includeDirs = std::vector<std::string>()); - bool ParseTypesFromSourceFile(const std::string& fileName, std::map<std::string, Ref<Type>>& types, - std::map<std::string, Ref<Type>>& variables, - std::map<std::string, Ref<Type>>& functions, std::string& errors, - const std::vector<std::string>& includeDirs = std::vector<std::string>()); + std::map<std::vector<std::string>, Ref<Type>>& types, + std::map<std::vector<std::string>, Ref<Type>>& variables, + std::map<std::vector<std::string>, Ref<Type>>& functions, std::string& errors, + const std::vector<std::string>& includeDirs = std::vector<std::string>()); + bool ParseTypesFromSourceFile(const std::string& fileName, + std::map<std::vector<std::string>, Ref<Type>>& types, + std::map<std::vector<std::string>, Ref<Type>>& variables, + std::map<std::vector<std::string>, Ref<Type>>& functions, std::string& errors, + const std::vector<std::string>& includeDirs = std::vector<std::string>()); void RegisterCallingConvention(CallingConvention* cc); std::vector<Ref<CallingConvention>> 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> type; }; + struct QualifiedNameAndType + { + std::vector<std::string> name; + Ref<Type> type; + }; + class Type: public CoreRefCountObject<BNType, BNNewTypeReference, BNFreeType> { public: @@ -1532,7 +1546,7 @@ namespace BinaryNinja bool CanReturn() const; Ref<Structure> GetStructure() const; Ref<Enumeration> GetEnumeration() const; - Ref<UnknownType> GetUnknownType() const; + Ref<NamedTypeReference> GetNamedTypeReference() const; uint64_t GetElementCount() const; @@ -1554,7 +1568,8 @@ namespace BinaryNinja static Ref<Type> IntegerType(size_t width, bool sign, const std::string& altName = ""); static Ref<Type> FloatType(size_t width, const std::string& typeName = ""); static Ref<Type> StructureType(Structure* strct); - static Ref<Type> UnknownNamedType(UnknownType* unknwn); + static Ref<Type> NamedType(NamedTypeReference* ref, size_t width = 0, size_t align = 1); + static Ref<Type> NamedType(const std::vector<std::string>& name, Type* type); static Ref<Type> EnumerationType(Architecture* arch, Enumeration* enm, size_t width = 0, bool issigned = false); static Ref<Type> 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<std::string>& names); }; - class UnknownType: public CoreRefCountObject<BNUnknownType, BNNewUnknownTypeReference, BNFreeUnknownType> + class NamedTypeReference: public CoreRefCountObject<BNNamedTypeReference, BNNewNamedTypeReference, + BNFreeNamedTypeReference> { public: - UnknownType(BNUnknownType* s, std::vector<std::string> name = {}); + NamedTypeReference(BNNamedTypeReference* nt); + NamedTypeReference(BNNamedTypeReferenceClass cls, const std::vector<std::string>& name = {}); + BNNamedTypeReferenceClass GetTypeClass() const; + void SetTypeClass(BNNamedTypeReferenceClass cls); std::vector<std::string> GetName() const; void SetName(const std::vector<std::string>& name); }; @@ -1586,8 +1605,6 @@ namespace BinaryNinja Structure(); Structure(BNStructure* s); - std::vector<std::string> GetName() const; - void SetName(const std::vector<std::string>& name); std::vector<StructureMember> GetMembers() const; uint64_t GetWidth() const; void SetWidth(size_t width); @@ -1616,9 +1633,6 @@ namespace BinaryNinja public: Enumeration(BNEnumeration* e); - std::vector<std::string> GetName() const; - void SetName(const std::vector<std::string>& name); - std::vector<EnumerationMember> 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<BinaryView> view = new BinaryView(BNNewViewReference(data)); Ref<Type> typeObj = new Type(BNNewTypeReference(type)); - notify->OnTypeDefined(view, name, typeObj); + vector<string> 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<BinaryView> view = new BinaryView(BNNewViewReference(data)); Ref<Type> typeObj = new Type(BNNewTypeReference(type)); - notify->OnTypeUndefined(view, name, typeObj); + vector<string> nameList; + for (size_t i = 0; i < nameCount; i++) + nameList.push_back(name[i]); + notify->OnTypeUndefined(view, nameList, typeObj); } @@ -1447,9 +1455,9 @@ vector<LinearDisassemblyLine> 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<string, Ref<Type>> BinaryView::GetTypes() +map<vector<string>, Ref<Type>> BinaryView::GetTypes() { size_t count; - BNNameAndType* types = BNGetAnalysisTypeList(m_object, &count); + BNQualifiedNameAndType* types = BNGetAnalysisTypeList(m_object, &count); - map<string, Ref<Type>> result; + map<vector<string>, Ref<Type>> result; for (size_t i = 0; i < count; i++) - result[types[i].name] = new Type(BNNewTypeReference(types[i].type)); + { + vector<string> 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<string, Ref<Type>> BinaryView::GetTypes() Ref<Type> 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<Type> BinaryView::GetTypeByName(const vector<string>& 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<string>& 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> type) +{ + const char* nameStr = name.c_str(); + BNDefineAnalysisType(m_object, &nameStr, 1, type->GetObject()); +} + + +void BinaryView::DefineType(const vector<string>& name, Ref<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(); + BNDefineAnalysisType(m_object, nameList, name.size(), type->GetObject()); + delete[] nameList; +} + + +void BinaryView::DefineUserType(const string& name, Ref<Type> type) +{ + const char* nameStr = name.c_str(); + BNDefineUserAnalysisType(m_object, &nameStr, 1, type->GetObject()); +} + + +void BinaryView::DefineUserType(const vector<string>& name, Ref<Type> 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> 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> type) +void BinaryView::UndefineType(const vector<string>& 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<string>& 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") (<type: int32_t>, '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): <type: int32_t> >>> """ - 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) <type: int32_t> """ - 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) <type: int32_t> """ - 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): """ @@ -4314,6 +4420,14 @@ class Type(object): 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)""" return core.BNGetTypeElementCount(self.handle) @@ -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 "<named type: typedef %s>" % str(self.name) + if self.type_class == core.StructNamedTypeClass: + return "<named type: struct %s>" % str(self.name) + if self.type_class == core.UnionNamedTypeClass: + return "<named type: union %s>" % str(self.name) + if self.type_class == core.EnumNamedTypeClass: + return "<named type: enum %s>" % str(self.name) + return "<named type: unknown %s>" % str(self.name) class StructureMember(object): @@ -4441,19 +4594,6 @@ class Structure(object): 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)""" count = ctypes.c_ulonglong() @@ -4539,14 +4679,6 @@ class Enumeration(object): 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)""" count = ctypes.c_ulonglong() @@ -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<string, Ref<Type>> types, vars, funcs; + map<vector<string>, Ref<Type>> 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<string, int64_t> 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"); @@ -133,6 +133,15 @@ Ref<Enumeration> Type::GetEnumeration() const } +Ref<NamedTypeReference> 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> Type::StructureType(Structure* strct) } -Ref<Type> Type::UnknownNamedType(UnknownType* unknwn) +Ref<Type> 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> Type::NamedType(const vector<string>& 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<string> names) +NamedTypeReference::NamedTypeReference(BNNamedTypeReference* nt) +{ + m_object = nt; +} + + +NamedTypeReference::NamedTypeReference(BNNamedTypeReferenceClass cls, const vector<string>& 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<string>& names) +void NamedTypeReference::SetTypeClass(BNNamedTypeReferenceClass cls) +{ + BNSetTypeReferenceClass(m_object, cls); +} + + +BNNamedTypeReferenceClass NamedTypeReference::GetTypeClass() const +{ + return BNGetTypeReferenceClass(m_object); +} + + +void NamedTypeReference::SetName(const vector<string>& 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<string> UnknownType::GetName() const +vector<string> NamedTypeReference::GetName() const { size_t size; - char** name = BNGetUnknownTypeName(m_object, &size); + char** name = BNGetTypeReferenceName(m_object, &size); vector<string> result; for (size_t i = 0; i < size; i++) { @@ -407,33 +447,6 @@ Structure::Structure(BNStructure* s) } -vector<string> Structure::GetName() const -{ - size_t size; - char** name = BNGetStructureName(m_object, &size); - vector<string> 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<string>& 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<StructureMember> Structure::GetMembers() const { size_t count; @@ -532,32 +545,6 @@ Enumeration::Enumeration(BNEnumeration* e) } -vector<string> Enumeration::GetName() const -{ - vector<string> 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<string>& 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<EnumerationMember> Enumeration::GetMembers() const { size_t count; |
