diff options
| author | Glenn Smith <glenn@vector35.com> | 2023-02-20 21:58:55 -0500 |
|---|---|---|
| committer | Glenn Smith <glenn@vector35.com> | 2023-11-06 16:10:47 -0500 |
| commit | 4108964609171327618627477163339656037111 (patch) | |
| tree | 79f4c6da6394b973cee05cc42b6edd7e2e20909d | |
| parent | b270d7ebe1e2a406e1f7f14807987d24b0c4a846 (diff) | |
Type Containers
| -rw-r--r-- | binaryninjaapi.h | 103 | ||||
| -rw-r--r-- | binaryninjacore.h | 68 | ||||
| -rw-r--r-- | binaryview.cpp | 22 | ||||
| -rw-r--r-- | debuginfo.cpp | 6 | ||||
| -rw-r--r-- | platform.cpp | 12 | ||||
| -rw-r--r-- | python/__init__.py | 1 | ||||
| -rw-r--r-- | python/binaryview.py | 18 | ||||
| -rw-r--r-- | python/debuginfo.py | 5 | ||||
| -rw-r--r-- | python/platform.py | 11 | ||||
| -rw-r--r-- | python/typecontainer.py | 246 | ||||
| -rw-r--r-- | python/typelibrary.py | 12 | ||||
| -rw-r--r-- | python/typeprinter.py | 30 | ||||
| -rw-r--r-- | python/types.py | 28 | ||||
| -rw-r--r-- | rust/src/types.rs | 9 | ||||
| -rw-r--r-- | suite/api_test.py | 9 | ||||
| -rw-r--r-- | type.cpp | 8 | ||||
| -rw-r--r-- | typecontainer.cpp | 406 | ||||
| -rw-r--r-- | typelibrary.cpp | 8 | ||||
| -rw-r--r-- | typeprinter.cpp | 9 | ||||
| -rw-r--r-- | ui/createtypedialog.h | 10 | ||||
| -rw-r--r-- | ui/uitypes.h | 1 |
21 files changed, 949 insertions, 73 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 7a4efee4..d32af5ce 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -5125,6 +5125,9 @@ namespace BinaryNinja { bool ParseTypesFromSource(const std::string& text, const std::vector<std::string>& options, const std::vector<std::string>& includeDirs, TypeParserResult& result, std::string& errors, const std::set<QualifiedName>& typesAllowRedefinition = {}); + class TypeContainer GetTypeContainer(); + class TypeContainer GetAutoTypeContainer(); + class TypeContainer GetUserTypeContainer(); std::map<QualifiedName, Ref<Type>> GetTypes(); /*! List of all types, sorted such that types are after all types on which they depend @@ -7881,7 +7884,7 @@ namespace BinaryNinja { bool AddTypeMemberTokens(BinaryView* data, std::vector<InstructionTextToken>& tokens, int64_t offset, std::vector<std::string>& nameList, size_t size = 0, bool indirect = false); - std::vector<TypeDefinitionLine> GetLines(Ref<BinaryView> data, const std::string& name, + std::vector<TypeDefinitionLine> GetLines(const TypeContainer& types, const std::string& name, int lineWidth = 80, bool collapsed = false, BNTokenEscapingType escaping = NoTokenEscapingType); static std::string GetSizeSuffix(size_t size); @@ -8138,7 +8141,7 @@ namespace BinaryNinja { \return The list of structure members */ - std::vector<InheritedStructureMember> GetMembersIncludingInherited(BinaryView* view) const; + std::vector<InheritedStructureMember> GetMembersIncludingInherited(const TypeContainer& types) const; /*! Get a structure member (including inherited members) at a certain offset @@ -8147,7 +8150,7 @@ namespace BinaryNinja { \param result Reference to a InheritedStructureMember to copy the result to \return Whether a member was found */ - bool GetMemberIncludingInheritedAtOffset(BinaryView* view, int64_t offset, + bool GetMemberIncludingInheritedAtOffset(BinaryView* view, int64_t offset, InheritedStructureMember& result) const; /*! Get a structure member by name @@ -13573,6 +13576,7 @@ namespace BinaryNinja { std::vector<Ref<TypeLibrary>> GetTypeLibrariesByName(const std::string& name); + TypeContainer GetTypeContainer(); Ref<Type> GetTypeByName(const QualifiedName& name); Ref<Type> GetVariableByName(const QualifiedName& name); @@ -13851,7 +13855,7 @@ namespace BinaryNinja { BNPlatform* platform, BNTokenEscapingType escaping, char** result); static bool GetTypeStringAfterNameCallback(void* ctxt, BNType* type, BNPlatform* platform, BNTokenEscapingType escaping, char** result); - static bool GetTypeLinesCallback(void* ctxt, BNType* type, BNBinaryView* data, + static bool GetTypeLinesCallback(void* ctxt, BNType* type, BNTypeContainer* types, BNQualifiedName* name, int lineWidth, bool collapsed, BNTokenEscapingType escaping, BNTypeDefinitionLine** result, size_t* resultCount); static bool PrintAllTypesCallback(void* ctxt, BNQualifiedName* names, BNType** types, size_t typeCount, @@ -13965,7 +13969,7 @@ namespace BinaryNinja { /*! Generate a multi-line representation of a type \param type Type to print - \param data Binary View in which the type is defined + \param types Type Container in which the type is defined \param name Name of the type \param lineWidth Maximum width of lines, in characters \param collapsed Whether to collapse structure/enum blocks @@ -13974,7 +13978,7 @@ namespace BinaryNinja { */ virtual std::vector<TypeDefinitionLine> GetTypeLines( Ref<Type> type, - Ref<BinaryView> data, + const TypeContainer& types, const QualifiedName& name, int lineWidth = 80, bool collapsed = false, @@ -14038,7 +14042,7 @@ namespace BinaryNinja { virtual std::string GetTypeStringAfterName(Ref<Type> type, Ref<Platform> platform, BNTokenEscapingType escaping) override; virtual std::vector<TypeDefinitionLine> GetTypeLines(Ref<Type> type, - Ref<BinaryView> data, const QualifiedName& name, int lineWidth, + const TypeContainer& types, const QualifiedName& name, int lineWidth, bool collapsed, BNTokenEscapingType escaping) override; virtual std::string PrintAllTypes(const std::vector<std::pair<QualifiedName, Ref<Type>>>& types, Ref<BinaryView> data, int lineWidth, BNTokenEscapingType escaping) override; @@ -15203,6 +15207,8 @@ namespace BinaryNinja { std::vector<std::string> GetParsers() const; + TypeContainer GetTypeContainer(const std::string& parserName); + std::vector<NameAndType> GetTypes(const std::string& parserName = "") const; std::vector<DebugFunctionInfo> GetFunctions(const std::string& parserName = "") const; std::vector<DataVariableAndName> GetDataVariables(const std::string& parserName = "") const; @@ -15625,6 +15631,12 @@ namespace BinaryNinja { */ void SetGuid(const std::string& guid); + /*! Get a TypeContainer interface for this type library + + \return Container interface + */ + TypeContainer GetTypeContainer(); + /*! Direct extracts a reference to a contained object -- when attempting to extract types from a library into a BinaryView, consider using BinaryView::ImportTypeLibraryObject instead. @@ -15746,6 +15758,61 @@ namespace BinaryNinja { void Finalize(); }; + class TypeContainer + { + BNTypeContainer* m_object; + + public: + explicit TypeContainer(BNTypeContainer* container); + explicit TypeContainer(TypeContainer&& other); + + TypeContainer(Ref<BinaryView> data); + TypeContainer(Ref<TypeLibrary> library); + TypeContainer(Ref<Platform> platform); + + ~TypeContainer(); + TypeContainer(const TypeContainer& other); + TypeContainer& operator=(const TypeContainer& other); + TypeContainer& operator=(TypeContainer&& other); + bool operator==(const TypeContainer& other) const { return GetId() == other.GetId(); } + bool operator!=(const TypeContainer& other) const { return !operator==(other); } + + BNTypeContainer* GetObject() const { return m_object; } + + std::string GetId() const; + std::string GetName() const; + BNTypeContainerType GetType() const; + bool IsMutable() const; + Ref<Platform> GetPlatform() const; + + std::optional<std::string> AddType(QualifiedName name, Ref<Type> type); + std::optional<std::unordered_map<QualifiedName, std::string>> AddTypes( + const std::vector<std::pair<QualifiedName, Ref<Type>>>& types, + std::function<bool(size_t, size_t)> progress = {}); + bool RenameType(const std::string& typeId, const QualifiedName& newName); + bool DeleteType(const std::string& typeId); + + std::optional<std::string> GetTypeId(const QualifiedName& typeName) const; + std::optional<QualifiedName> GetTypeName(const std::string& typeId) const; + std::optional<Ref<Type>> GetTypeById(const std::string& typeId) const; + std::optional<std::unordered_map<std::string, std::pair<QualifiedName, Ref<Type>>>> GetTypes() const; + + std::optional<Ref<Type>> GetTypeByName(const QualifiedName& typeName) const; + std::optional<std::unordered_set<std::string>> GetTypeIds() const; + std::optional<std::unordered_set<QualifiedName>> GetTypeNames() const; + std::optional<std::unordered_map<std::string, QualifiedName>> GetTypeNamesAndIds() const; + + bool ParseTypesFromSource( + const std::string& text, + const std::string& fileName, + const std::vector<std::string>& options, + const std::vector<std::string>& includeDirs, + const std::string& autoTypeSource, + TypeParserResult& result, + std::vector<TypeParserError>& errors + ); + }; + /*! \ingroup binaryview */ @@ -15764,3 +15831,25 @@ namespace BinaryNinja { void Process(); }; } // namespace BinaryNinja + + +namespace std +{ + template<> struct hash<BinaryNinja::QualifiedName> + { + typedef BinaryNinja::QualifiedName argument_type; + size_t operator()(argument_type const& value) const + { + return std::hash<std::string>()(value.GetString()); + } + }; + + template<typename T> struct hash<BinaryNinja::Ref<T>> + { + typedef BinaryNinja::Ref<T> argument_type; + size_t operator()(argument_type const& value) const + { + return std::hash<decltype(T::GetObject(value.GetPtr()))>()(T::GetObject(value.GetPtr())); + } + }; +} // namespace std diff --git a/binaryninjacore.h b/binaryninjacore.h index a92c7a09..6f46326a 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -37,14 +37,14 @@ // Current ABI version for linking to the core. This is incremented any time // there are changes to the API that affect linking, including new functions, // new types, or modifications to existing functions or types. -#define BN_CURRENT_CORE_ABI_VERSION 40 +#define BN_CURRENT_CORE_ABI_VERSION 41 // Minimum ABI version that is supported for loading of plugins. Plugins that // are linked to an ABI version less than this will not be able to load and // will require rebuilding. The minimum version is increased when there are // incompatible changes that break binary compatibility, such as changes to // existing types or functions. -#define BN_MINIMUM_CORE_ABI_VERSION 40 +#define BN_MINIMUM_CORE_ABI_VERSION 41 #ifdef __GNUC__ #ifdef BINARYNINJACORE_LIBRARY @@ -264,7 +264,7 @@ extern "C" typedef struct BNSecretsProvider BNSecretsProvider; typedef struct BNLogger BNLogger; typedef struct BNSymbolQueue BNSymbolQueue; - + typedef struct BNTypeContainer BNTypeContainer; //! Console log levels typedef enum BNLogLevel @@ -2629,8 +2629,8 @@ extern "C" BNPlatform* platform, BNTokenEscapingType escaping, char** result); bool (*getTypeStringAfterName)(void* ctxt, BNType* type, BNPlatform* platform, BNTokenEscapingType escaping, char** result); - bool (*getTypeLines)(void* ctxt, BNType* type, BNBinaryView* data, - BNQualifiedName* name, int lineWidth, bool collapsed, + bool (*getTypeLines)(void* ctxt, BNType* type, BNTypeContainer* types, BNQualifiedName* name, + int lineWidth, bool collapsed, BNTokenEscapingType escaping, BNTypeDefinitionLine** result, size_t* resultCount); bool (*printAllTypes)(void* ctxt, BNQualifiedName* names, BNType** types, size_t typeCount, BNBinaryView* data, int lineWidth, BNTokenEscapingType escaping, char** result); @@ -2989,6 +2989,17 @@ extern "C" void (*licenseStatusChanged)(void* ctxt, bool stillValid); } BNEnterpriseServerCallbacks; + typedef enum BNTypeContainerType + { + AnalysisTypeContainerType, + AnalysisAutoTypeContainerType, + AnalysisUserTypeContainerType, + TypeLibraryTypeContainerType, + TypeArchiveTypeContainerType, + DebugInfoTypeContainerType, + PlatformTypeContainerType, + } BNTypeContainerType; + BINARYNINJACOREAPI char* BNAllocString(const char* contents); BINARYNINJACOREAPI void BNFreeString(char* str); BINARYNINJACOREAPI char** BNAllocStringList(const char** contents, size_t size); @@ -4386,10 +4397,13 @@ extern "C" BINARYNINJACOREAPI BNQualifiedNameAndType* BNGetAnalysisTypeList(BNBinaryView* view, size_t* count); BINARYNINJACOREAPI BNQualifiedNameAndType* BNGetAnalysisDependencySortedTypeList(BNBinaryView* view, size_t* count); - BINARYNINJACOREAPI void BNFreeTypeList(BNQualifiedNameAndType* types, size_t count); + BINARYNINJACOREAPI void BNFreeTypeAndNameList(BNQualifiedNameAndType* types, size_t count); BINARYNINJACOREAPI void BNFreeTypeIdList(BNQualifiedNameTypeAndId* types, size_t count); BINARYNINJACOREAPI BNQualifiedName* BNGetAnalysisTypeNames(BNBinaryView* view, size_t* count, const char* matching); BINARYNINJACOREAPI void BNFreeTypeNameList(BNQualifiedName* names, size_t count); + BINARYNINJACOREAPI BNTypeContainer* BNGetAnalysisTypeContainer(BNBinaryView* view); + BINARYNINJACOREAPI BNTypeContainer* BNGetAnalysisAutoTypeContainer(BNBinaryView* view); + BINARYNINJACOREAPI BNTypeContainer* BNGetAnalysisUserTypeContainer(BNBinaryView* view); BINARYNINJACOREAPI BNType* BNGetAnalysisTypeByName(BNBinaryView* view, BNQualifiedName* name); BINARYNINJACOREAPI BNType* BNGetAnalysisTypeByRef(BNBinaryView* view, BNNamedTypeReference* ref); BINARYNINJACOREAPI BNType* BNGetAnalysisTypeById(BNBinaryView* view, const char* id); @@ -4436,6 +4450,32 @@ extern "C" BINARYNINJACOREAPI void BNSetAutoBasicBlockHighlight(BNBasicBlock* block, BNHighlightColor color); BINARYNINJACOREAPI void BNSetUserBasicBlockHighlight(BNBasicBlock* block, BNHighlightColor color); + BINARYNINJACOREAPI void BNFreeTypeContainer(BNTypeContainer* container); + BINARYNINJACOREAPI BNTypeContainer* BNDuplicateTypeContainer(BNTypeContainer* container); + BINARYNINJACOREAPI char* BNTypeContainerGetId(BNTypeContainer* container); + BINARYNINJACOREAPI char* BNTypeContainerGetName(BNTypeContainer* container); + BINARYNINJACOREAPI BNTypeContainerType BNTypeContainerGetType(BNTypeContainer* container); + BINARYNINJACOREAPI bool BNTypeContainerIsMutable(BNTypeContainer* container); + BINARYNINJACOREAPI BNPlatform* BNTypeContainerGetPlatform(BNTypeContainer* container); + BINARYNINJACOREAPI bool BNTypeContainerAddTypes(BNTypeContainer* container, const BNQualifiedName* typeNames, BNType** types, size_t typeCount, bool(*progress)(void*, size_t, size_t), void* progressContext, BNQualifiedName** resultNames, char*** resultIds, size_t* resultCount); + BINARYNINJACOREAPI bool BNTypeContainerRenameType(BNTypeContainer* container, const char* typeId, const BNQualifiedName* newName); + BINARYNINJACOREAPI bool BNTypeContainerDeleteType(BNTypeContainer* container, const char* typeId); + BINARYNINJACOREAPI bool BNTypeContainerGetTypeId(BNTypeContainer* container, const BNQualifiedName* typeName, char** result); + BINARYNINJACOREAPI bool BNTypeContainerGetTypeName(BNTypeContainer* container, const char* typeId, BNQualifiedName* result); + BINARYNINJACOREAPI bool BNTypeContainerGetTypeById(BNTypeContainer* container, const char* typeId, BNType** result); + BINARYNINJACOREAPI bool BNTypeContainerGetTypes(BNTypeContainer* container, char*** typeIds, BNQualifiedName** typeNames, BNType*** types, size_t* count); + BINARYNINJACOREAPI bool BNTypeContainerGetTypeByName(BNTypeContainer* container, const BNQualifiedName* typeName, BNType** result); + BINARYNINJACOREAPI bool BNTypeContainerGetTypeIds(BNTypeContainer* container, char*** typeIds, size_t* count); + BINARYNINJACOREAPI bool BNTypeContainerGetTypeNames(BNTypeContainer* container, BNQualifiedName** typeNames, size_t* count); + BINARYNINJACOREAPI bool BNTypeContainerGetTypeNamesAndIds(BNTypeContainer* container, char*** typeIds, BNQualifiedName** typeNames, size_t* count); + BINARYNINJACOREAPI bool BNTypeContainerParseTypesFromSource(BNTypeContainer* container, + const char* source, const char* fileName, + const char* const* options, size_t optionCount, + const char* const* includeDirs, size_t includeDirCount, + const char* autoTypeSource, BNTypeParserResult* result, + BNTypeParserError** errors, size_t* errorCount + ); + BINARYNINJACOREAPI BNTagType* BNCreateTagType(BNBinaryView* view); BINARYNINJACOREAPI BNTagType* BNNewTagTypeReference(BNTagType* tagType); BINARYNINJACOREAPI void BNFreeTagType(BNTagType* tagType); @@ -5277,6 +5317,8 @@ extern "C" BINARYNINJACOREAPI BNMetadata* BNTypeLibraryQueryMetadata(BNTypeLibrary* lib, const char* key); BINARYNINJACOREAPI void BNTypeLibraryRemoveMetadata(BNTypeLibrary* lib, const char* key); + BINARYNINJACOREAPI BNTypeContainer* BNGetTypeLibraryTypeContainer(BNTypeLibrary* lib); + BINARYNINJACOREAPI void BNAddTypeLibraryNamedObject(BNTypeLibrary* lib, BNQualifiedName* name, BNType* type); BINARYNINJACOREAPI void BNAddTypeLibraryNamedType(BNTypeLibrary* lib, BNQualifiedName* name, BNType* type); BINARYNINJACOREAPI void BNAddTypeLibraryNamedTypeSource(BNTypeLibrary* lib, BNQualifiedName* name, const char* source); @@ -5348,6 +5390,7 @@ extern "C" BINARYNINJACOREAPI BNType* BNDuplicateType(BNType* type); BINARYNINJACOREAPI char* BNGetTypeAndName(BNType* type, BNQualifiedName* name, BNTokenEscapingType escaping); BINARYNINJACOREAPI void BNFreeType(BNType* type); + BINARYNINJACOREAPI void BNFreeTypeList(BNType** types, size_t count); BINARYNINJACOREAPI BNTypeBuilder* BNCreateTypeBuilderFromType(BNType* type); BINARYNINJACOREAPI BNTypeBuilder* BNCreateVoidTypeBuilder(void); @@ -5426,7 +5469,7 @@ extern "C" BINARYNINJACOREAPI bool BNAddTypeMemberTokens(BNType* type, BNBinaryView* data, BNInstructionTextToken** tokens, size_t* tokenCount, int64_t offset, char*** nameList, size_t* nameCount, size_t size, bool indirect); - BINARYNINJACOREAPI BNTypeDefinitionLine* BNGetTypeLines(BNType* type, BNBinaryView* data, const char* name, int lineWidth, bool collapsed, BNTokenEscapingType escaping, size_t* count); + BINARYNINJACOREAPI BNTypeDefinitionLine* BNGetTypeLines(BNType* type, BNTypeContainer* types, const char* name, int lineWidth, bool collapsed, BNTokenEscapingType escaping, size_t* count); BINARYNINJACOREAPI void BNFreeTypeDefinitionLineList(BNTypeDefinitionLine* list, size_t count); BINARYNINJACOREAPI BNQualifiedName BNTypeBuilderGetTypeName(BNTypeBuilder* nt); @@ -5498,6 +5541,7 @@ extern "C" BINARYNINJACOREAPI char* BNGetTypeReferenceId(BNNamedTypeReference* nt); BINARYNINJACOREAPI BNQualifiedName BNGetTypeReferenceName(BNNamedTypeReference* nt); BINARYNINJACOREAPI void BNFreeQualifiedName(BNQualifiedName* name); + BINARYNINJACOREAPI void BNFreeQualifiedNameArray(BNQualifiedName* names, size_t count); BINARYNINJACOREAPI void BNFreeNamedTypeReference(BNNamedTypeReference* nt); BINARYNINJACOREAPI BNNamedTypeReference* BNNewNamedTypeReference(BNNamedTypeReference* nt); @@ -5528,7 +5572,7 @@ extern "C" BINARYNINJACOREAPI BNStructureMember* BNGetStructureMembers(BNStructure* s, size_t* count); BINARYNINJACOREAPI void BNFreeStructureMemberList(BNStructureMember* members, size_t count); BINARYNINJACOREAPI BNInheritedStructureMember* BNGetStructureMembersIncludingInherited( - BNStructure* s, BNBinaryView* view, size_t* count); + BNStructure* s, BNTypeContainer* types, size_t* count); BINARYNINJACOREAPI void BNFreeInheritedStructureMemberList(BNInheritedStructureMember* members, size_t count); BINARYNINJACOREAPI BNInheritedStructureMember* BNGetMemberIncludingInheritedAtOffset(BNStructure* s, BNBinaryView* view, int64_t offset); @@ -5697,9 +5741,9 @@ extern "C" BINARYNINJACOREAPI bool BNGetTypePrinterTypeStringAfterName(BNTypePrinter* printer, BNType* type, BNPlatform* platform, BNTokenEscapingType escaping, char** result); BINARYNINJACOREAPI bool BNGetTypePrinterTypeLines(BNTypePrinter* printer, - BNType* type, BNBinaryView* data, - BNQualifiedName* name, int lineWidth, bool collapsed, - BNTokenEscapingType escaping, BNTypeDefinitionLine** result, size_t* resultCount); + BNType* type, BNTypeContainer* types, BNQualifiedName* name, + int lineWidth, bool collapsed, BNTokenEscapingType escaping, + BNTypeDefinitionLine** result, size_t* resultCount); BINARYNINJACOREAPI bool BNTypePrinterPrintAllTypes(BNTypePrinter* printer, BNQualifiedName* names, BNType** types, size_t typeCount, BNBinaryView* data, int lineWidth, BNTokenEscapingType escaping, char** result); BINARYNINJACOREAPI bool BNTypePrinterDefaultPrintAllTypes(BNTypePrinter* printer, BNQualifiedName* names, BNType** types, @@ -5896,6 +5940,7 @@ extern "C" BINARYNINJACOREAPI void BNAddRelatedPlatform(BNPlatform* platform, BNArchitecture* arch, BNPlatform* related); BINARYNINJACOREAPI BNPlatform* BNGetAssociatedPlatformByAddress(BNPlatform* platform, uint64_t* addr); + BINARYNINJACOREAPI BNTypeContainer* BNGetPlatformTypeContainer(BNPlatform* platform); BINARYNINJACOREAPI BNQualifiedNameAndType* BNGetPlatformTypes(BNPlatform* platform, size_t* count); BINARYNINJACOREAPI BNQualifiedNameAndType* BNGetPlatformVariables(BNPlatform* platform, size_t* count); BINARYNINJACOREAPI BNQualifiedNameAndType* BNGetPlatformFunctions(BNPlatform* platform, size_t* count); @@ -6500,6 +6545,7 @@ extern "C" BINARYNINJACOREAPI BNDebugInfo* BNNewDebugInfoReference(BNDebugInfo* debugInfo); BINARYNINJACOREAPI void BNFreeDebugInfoReference(BNDebugInfo* debugInfo); BINARYNINJACOREAPI char** BNGetDebugParserNames(BNDebugInfo* const debugInfo, size_t* count); + BINARYNINJACOREAPI BNTypeContainer* BNGetDebugInfoTypeContainer(BNDebugInfo* debugInfo, const char* const parserName); BINARYNINJACOREAPI bool BNRemoveDebugParserInfo(BNDebugInfo* const debugInfo, const char* const parserName); BINARYNINJACOREAPI bool BNRemoveDebugParserTypes(BNDebugInfo* const debugInfo, const char* const parserName); BINARYNINJACOREAPI bool BNRemoveDebugParserFunctions(BNDebugInfo* const debugInfo, const char* const parserName); diff --git a/binaryview.cpp b/binaryview.cpp index 219a37e5..4bbd3aa3 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -3611,6 +3611,24 @@ bool BinaryView::ParseTypesFromSource(const string& source, const vector<string> } +TypeContainer BinaryView::GetTypeContainer() +{ + return TypeContainer(BNGetAnalysisTypeContainer(m_object)); +} + + +TypeContainer BinaryView::GetAutoTypeContainer() +{ + return TypeContainer(BNGetAnalysisAutoTypeContainer(m_object)); +} + + +TypeContainer BinaryView::GetUserTypeContainer() +{ + return TypeContainer(BNGetAnalysisUserTypeContainer(m_object)); +} + + map<QualifiedName, Ref<Type>> BinaryView::GetTypes() { size_t count; @@ -3623,7 +3641,7 @@ map<QualifiedName, Ref<Type>> BinaryView::GetTypes() result[name] = new Type(BNNewTypeReference(types[i].type)); } - BNFreeTypeList(types, count); + BNFreeTypeAndNameList(types, count); return result; } @@ -3640,7 +3658,7 @@ vector<pair<QualifiedName, Ref<Type>>> BinaryView::GetDependencySortedTypes() result.emplace_back(name, new Type(BNNewTypeReference(types[i].type))); } - BNFreeTypeList(types, count); + BNFreeTypeAndNameList(types, count); return result; } diff --git a/debuginfo.cpp b/debuginfo.cpp index 5f4e1af0..5fef18d2 100644 --- a/debuginfo.cpp +++ b/debuginfo.cpp @@ -54,6 +54,12 @@ vector<string> DebugInfo::GetParsers() const } +TypeContainer DebugInfo::GetTypeContainer(const std::string& parserName) +{ + return TypeContainer(BNGetDebugInfoTypeContainer(m_object, parserName.c_str())); +} + + vector<NameAndType> DebugInfo::GetTypes(const string& parserName) const { size_t count; diff --git a/platform.cpp b/platform.cpp index e7f3aef5..de7b50c8 100644 --- a/platform.cpp +++ b/platform.cpp @@ -284,7 +284,7 @@ map<QualifiedName, Ref<Type>> Platform::GetTypes() result[name] = new Type(BNNewTypeReference(types[i].type)); } - BNFreeTypeList(types, count); + BNFreeTypeAndNameList(types, count); return result; } @@ -301,7 +301,7 @@ map<QualifiedName, Ref<Type>> Platform::GetVariables() result[name] = new Type(BNNewTypeReference(types[i].type)); } - BNFreeTypeList(types, count); + BNFreeTypeAndNameList(types, count); return result; } @@ -318,7 +318,7 @@ map<QualifiedName, Ref<Type>> Platform::GetFunctions() result[name] = new Type(BNNewTypeReference(types[i].type)); } - BNFreeTypeList(types, count); + BNFreeTypeAndNameList(types, count); return result; } @@ -374,6 +374,12 @@ vector<Ref<TypeLibrary>> Platform::GetTypeLibrariesByName(const std::string& nam } +TypeContainer Platform::GetTypeContainer() +{ + return TypeContainer(BNGetPlatformTypeContainer(m_object)); +} + + Ref<Type> Platform::GetTypeByName(const QualifiedName& name) { BNQualifiedName nameObj = name.GetAPIObject(); diff --git a/python/__init__.py b/python/__init__.py index 4a9d1d1c..2fddefe4 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -69,6 +69,7 @@ from .secretsprovider import * from .typeparser import * from .typeprinter import * from .component import * +from .typecontainer import * # We import each of these by name to prevent conflicts between # log.py and the function 'log' which we don't import below from .log import ( diff --git a/python/binaryview.py b/python/binaryview.py index cd7a0cdf..d7d2a2a8 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -71,6 +71,7 @@ from . import function as _function from . import types as _types from . import platform as _platform from . import deprecation +from . import typecontainer PathType = Union[str, os.PathLike] InstructionsType = Generator[Tuple[List['_function.InstructionTextToken'], int], None, None] @@ -1745,7 +1746,7 @@ class TypeMapping(collections.abc.Mapping): # type: ignore def __del__(self): if core is not None and self._type_list is not None: - core.BNFreeTypeList(self._type_list, len(self)) + core.BNFreeTypeAndNameList(self._type_list, len(self)) def __getitem__(self, key): if self._type_cache is None: @@ -6958,6 +6959,21 @@ class BinaryView: raise ValueError(error_str) return variable.PossibleValueSet(self.arch, result) + @property + def type_container(self) -> 'typecontainer.TypeContainer': + container = core.BNGetAnalysisTypeContainer(self.handle) + return typecontainer.TypeContainer(handle=container) + + @property + def auto_type_container(self) -> 'typecontainer.TypeContainer': + container = core.BNGetAnalysisAutoTypeContainer(self.handle) + return typecontainer.TypeContainer(handle=container) + + @property + def user_type_container(self) -> 'typecontainer.TypeContainer': + container = core.BNGetAnalysisUserTypeContainer(self.handle) + return typecontainer.TypeContainer(handle=container) + def get_type_by_name(self, name: '_types.QualifiedNameType') -> Optional['_types.Type']: """ ``get_type_by_name`` returns the defined type whose name corresponds with the provided ``name`` diff --git a/python/debuginfo.py b/python/debuginfo.py index 1b9bc712..65f879ea 100644 --- a/python/debuginfo.py +++ b/python/debuginfo.py @@ -31,6 +31,7 @@ from . import types as _types from .log import log_error from . import binaryview from . import filemetadata +from . import typecontainer _debug_info_parsers = {} ProgressFuncType = Callable[[int, int], bool] @@ -303,6 +304,10 @@ class DebugInfo(object): core.BNFreeStringList(parsers, count.value) + def get_type_container(self, parser_name: str) -> 'typecontainer.TypeContainer': + """Returns a TypeContainer interface for one of the parsers in this DebugInfo""" + return typecontainer.TypeContainer(core.BNGetDebugInfoTypeContainer(self.handle, parser_name)) + def types_from_parser(self, name: Optional[str] = None) -> Iterator[Tuple[str, _types.Type]]: """Returns a generator of all types provided by a named DebugInfoParser""" count = ctypes.c_ulonglong(0) diff --git a/python/platform.py b/python/platform.py index e60f9a8f..2c4a26f6 100644 --- a/python/platform.py +++ b/python/platform.py @@ -30,6 +30,7 @@ from . import typeparser from . import callingconvention from . import typelibrary from . import architecture +from . import typecontainer class _PlatformMetaClass(type): @@ -262,7 +263,7 @@ class Platform(metaclass=_PlatformMetaClass): for i in range(0, count.value): name = types.QualifiedName._from_core_struct(type_list[i].name) result[name] = types.Type.create(core.BNNewTypeReference(type_list[i].type), platform=self) - core.BNFreeTypeList(type_list, count.value) + core.BNFreeTypeAndNameList(type_list, count.value) return result @property @@ -275,7 +276,7 @@ class Platform(metaclass=_PlatformMetaClass): for i in range(0, count.value): name = types.QualifiedName._from_core_struct(type_list[i].name) result[name] = types.Type.create(core.BNNewTypeReference(type_list[i].type), platform=self) - core.BNFreeTypeList(type_list, count.value) + core.BNFreeTypeAndNameList(type_list, count.value) return result @property @@ -288,7 +289,7 @@ class Platform(metaclass=_PlatformMetaClass): for i in range(0, count.value): name = types.QualifiedName._from_core_struct(type_list[i].name) result[name] = types.Type.create(core.BNNewTypeReference(type_list[i].type), platform=self) - core.BNFreeTypeList(type_list, count.value) + core.BNFreeTypeAndNameList(type_list, count.value) return result @property @@ -359,6 +360,10 @@ class Platform(metaclass=_PlatformMetaClass): result = core.BNGetAssociatedPlatformByAddress(self.handle, new_addr) return Platform(handle=result), new_addr.value + @property + def type_container(self) -> 'typecontainer.TypeContainer': + return typecontainer.TypeContainer(core.BNGetPlatformTypeContainer(self.handle)) + def get_type_by_name(self, name): name = types.QualifiedName(name)._to_core_struct() obj = core.BNGetPlatformTypeByName(self.handle, name) diff --git a/python/typecontainer.py b/python/typecontainer.py new file mode 100644 index 00000000..3f371213 --- /dev/null +++ b/python/typecontainer.py @@ -0,0 +1,246 @@ +# Copyright (c) 2015-2023 Vector 35 Inc +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import ctypes +from typing import Optional, Mapping, Callable, List, Tuple + +# Binary Ninja components +import binaryninja +from . import _binaryninjacore as core +from . import types as ty_ +from . import platform +from . import typeparser +from . import enums + + +ProgressFuncType = Callable[[int, int], bool] + + +class TypeContainer: + def __init__(self, handle: core.BNTypeContainerHandle): + binaryninja._init_plugins() + self.handle: core.BNTypeContainerHandle = core.handle_of_type(handle, core.BNTypeContainer) + + def __del__(self): + if core is not None: + core.BNFreeTypeContainer(self.handle) + + def __repr__(self): + return f"<type container {self.name}>" + + @property + def id(self) -> str: + return core.BNTypeContainerGetId(self.handle) + + @property + def name(self) -> str: + return core.BNTypeContainerGetName(self.handle) + + @property + def container_type(self) -> 'enums.TypeContainerType': + return core.BNTypeContainerGetType(self.handle) + + @property + def mutable(self) -> bool: + return core.BNTypeContainerIsMutable(self.handle) + + @property + def platform(self) -> 'platform.Platform': + handle = core.BNTypeContainerGetPlatform(self.handle) + assert handle is not None + return platform.Platform(handle=handle) + + def add_types(self, types: Mapping['ty_.QualifiedNameType', 'ty_.Type'], progress_func: Optional[ProgressFuncType] = None) -> Optional[Mapping['ty_.QualifiedName', str]]: + api_names = (core.BNQualifiedName * len(types))() + api_types = (ctypes.POINTER(core.BNType) * len(types))() + for (i, (key, value)) in enumerate(types.items()): + api_names[i] = ty_.QualifiedName(key)._to_core_struct() + api_types[i] = value.handle + + if progress_func: + progress_func_obj = ctypes.CFUNCTYPE( + ctypes.c_bool, ctypes.c_void_p, ctypes.c_ulonglong, ctypes.c_ulonglong + )(lambda ctxt, cur, total: progress_func(cur, total)) + else: + progress_func_obj = ctypes.CFUNCTYPE( + ctypes.c_bool, ctypes.c_void_p, ctypes.c_ulonglong, ctypes.c_ulonglong + )(lambda ctxt, cur, total: True) + + result_names = ctypes.POINTER(core.BNQualifiedName)() + result_ids = ctypes.POINTER(ctypes.c_char_p)() + result_count = ctypes.c_size_t(0) + + if not core.BNTypeContainerAddTypes(self.handle, api_names, api_types, len(types), progress_func_obj, None, result_names, result_ids, result_count): + return None + + result = {} + for i in range(result_count.value): + name = ty_.QualifiedName._from_core_struct(result_names[i]) + id = core.pyNativeStr(result_ids[i]) + result[name] = id + + core.BNFreeTypeNameList(result_names, result_count.value) + core.BNFreeStringList(result_ids, result_count.value) + return result + + def rename_type(self, type_id: str, new_name: 'ty_.QualifiedNameType') -> bool: + return core.BNTypeContainerRenameType(self.handle, type_id, ty_.QualifiedName(new_name)._to_core_struct()) + + def delete_type(self, type_id: str) -> bool: + return core.BNTypeContainerDeleteType(self.handle, type_id) + + def get_type_id(self, type_name: 'ty_.QualifiedNameType') -> Optional[str]: + result = ctypes.c_char_p() + if not core.BNTypeContainerGetTypeId(self.handle, ty_.QualifiedName(type_name)._to_core_struct(), result): + return None + return core.pyNativeStr(result.value) + + def get_type_name(self, type_id: str) -> Optional['ty_.QualifiedName']: + api_result = core.BNQualifiedName() + if not core.BNTypeContainerGetTypeName(self.handle, type_id, api_result): + return None + result = ty_.QualifiedName._from_core_struct(api_result) + core.BNFreeQualifiedName(api_result) + return result + + def get_type_by_id(self, type_id: str) -> Optional['ty_.Type']: + result = ctypes.POINTER(core.BNType)() + if not core.BNTypeContainerGetTypeById(self.handle, type_id, result): + return None + return ty_.Type(handle=result) + + @property + def types(self) -> Optional[Mapping[str, Tuple['ty_.QualifiedName', 'ty_.Type']]]: + result_names = ctypes.POINTER(core.BNQualifiedName)() + result_ids = ctypes.POINTER(ctypes.c_char_p)() + result_types = ctypes.POINTER(ctypes.POINTER(core.BNType))() + result_count = ctypes.c_size_t(0) + + if not core.BNTypeContainerGetTypes(self.handle, result_ids, result_names, result_types, result_count): + return None + + result = {} + for i in range(result_count.value): + name = ty_.QualifiedName._from_core_struct(result_names[i]) + id = core.pyNativeStr(result_ids[i]) + type = ty_.Type(handle=core.BNNewTypeReference(result_types[i])) + result[id] = (name, type) + + core.BNFreeTypeNameList(result_names, result_count.value) + core.BNFreeStringList(result_ids, result_count.value) + core.BNFreeTypeList(result_types, result_count.value) + return result + + def get_type_by_name(self, type_name: 'ty_.QualifiedNameType') -> Optional['ty_.Type']: + result = ctypes.POINTER(core.BNType)() + if not core.BNTypeContainerGetTypeByName(self.handle, ty_.QualifiedName(type_name)._to_core_struct(), result): + return None + return ty_.Type(handle=result) + + @property + def type_ids(self) -> Optional[List[str]]: + result_ids = ctypes.POINTER(ctypes.c_char_p)() + result_count = ctypes.c_size_t(0) + if not core.BNTypeContainerGetTypeIds(self.handle, result_ids, result_count): + return None + + result = [] + for i in range(result_count.value): + id = core.pyNativeStr(result_ids[i]) + result.append(id) + + core.BNFreeStringList(result_ids, result_count.value) + return result + + @property + def type_names(self) -> Optional[List['ty_.QualifiedName']]: + result_names = ctypes.POINTER(core.BNQualifiedName)() + result_count = ctypes.c_size_t(0) + if not core.BNTypeContainerGetTypeNames(self.handle, result_names, result_count): + return None + + result = [] + for i in range(result_count.value): + name = ty_.QualifiedName._from_core_struct(result_names[i]) + result.append(name) + + core.BNFreeTypeNameList(result_names, result_count.value) + return result + + @property + def type_names_and_ids(self) -> Optional[Mapping[str, 'ty_.QualifiedName']]: + result_names = ctypes.POINTER(core.BNQualifiedName)() + result_ids = ctypes.POINTER(ctypes.c_char_p)() + result_count = ctypes.c_size_t(0) + if not core.BNTypeContainerGetTypeNamesAndIds(self.handle, result_ids, result_names, result_count): + return None + + result = {} + for i in range(result_count.value): + name = ty_.QualifiedName._from_core_struct(result_names[i]) + id = core.pyNativeStr(result_ids[i]) + result[id] = name + + core.BNFreeTypeNameList(result_names, result_count.value) + core.BNFreeStringList(result_ids, result_count.value) + return result + + def parse_types_from_source(self, source: str, file_name: str, platform: 'platform.Platform', + options: Optional[List[str]] = None, include_dirs: Optional[List[str]] = None, + auto_type_source: str = "" + ) -> Tuple[Optional['typeparser.TypeParserResult'], List['typeparser.TypeParserError']]: + if options is None: + options = [] + if include_dirs is None: + include_dirs = [] + + options_cpp = (ctypes.c_char_p * len(options))() + for (i, s) in enumerate(options): + options_cpp[i] = core.cstr(s) + + include_dirs_cpp = (ctypes.c_char_p * len(include_dirs))() + for (i, s) in enumerate(include_dirs): + include_dirs_cpp[i] = core.cstr(s) + + result_cpp = core.BNTypeParserResult() + errors_cpp = ctypes.POINTER(core.BNTypeParserError)() + error_count = ctypes.c_size_t() + + success = core.BNTypeContainerParseTypesFromSource( + self.handle, source, file_name, platform.handle, + options_cpp, len(options), + include_dirs_cpp, len(include_dirs), auto_type_source, + result_cpp, errors_cpp, error_count + ) + + if success: + result = typeparser.TypeParserResult._from_core_struct(result_cpp) + else: + result = None + core.BNFreeTypeParserResult(result_cpp) + + errors = [] + for i in range(error_count.value): + errors.append(typeparser.TypeParserError._from_core_struct(errors_cpp[i])) + core.BNFreeTypeParserErrors(errors_cpp, error_count.value) + + return result, errors + + diff --git a/python/typelibrary.py b/python/typelibrary.py index 53f3e8ef..364a458d 100644 --- a/python/typelibrary.py +++ b/python/typelibrary.py @@ -28,6 +28,7 @@ from . import types from . import metadata from . import platform from . import architecture +from . import typecontainer class TypeLibrary: @@ -227,7 +228,7 @@ class TypeLibrary: """ return core.BNFinalizeTypeLibrary(self.handle) - def query_metadata(self, key: str) -> Optional[metadata.Metadata]: + def query_metadata(self, key: str) -> Optional['metadata.MetadataValueType']: """ `query_metadata` retrieves a metadata associated with the given key stored in the type library @@ -281,6 +282,15 @@ class TypeLibrary: """ core.BNTypeLibraryRemoveMetadata(self.handle, key) + @property + def type_container(self) -> 'typecontainer.TypeContainer': + """ + `type_container` returns a TypeContainer interface for interacting with the type library. + + :return: TypeContainer interface + """ + return typecontainer.TypeContainer(core.BNGetTypeLibraryTypeContainer(self.handle)) + def add_named_object(self, name: 'types.QualifiedName', type: 'types.Type') -> None: """ `add_named_object` directly inserts a named object into the type library's object store. diff --git a/python/typeprinter.py b/python/typeprinter.py index d7af3087..d6bf579e 100644 --- a/python/typeprinter.py +++ b/python/typeprinter.py @@ -35,6 +35,7 @@ from . import platform as _platform from . import types from . import function as _function from . import binaryview +from . import typecontainer from .log import log_error from .enums import TokenEscapingType @@ -220,11 +221,11 @@ class TypePrinter(metaclass=_TypePrinterMetaclass): log_error(traceback.format_exc()) return False - def _get_type_lines(self, ctxt, type, data, name, line_width, collapsed, escaping, result, result_count): + def _get_type_lines(self, ctxt, type, container, name, line_width, collapsed, escaping, result, result_count): try: result_py = self.get_type_lines( types.Type.create(handle=core.BNNewTypeReference(type)), - binaryview.BinaryView(handle=core.BNNewViewReference(data)), + typecontainer.TypeContainer(handle=container), types.QualifiedName._from_core_struct(name.contents), line_width, collapsed, escaping) @@ -378,12 +379,12 @@ class TypePrinter(metaclass=_TypePrinterMetaclass): """ raise NotImplementedError() - def get_type_lines(self, type: types.Type, data: binaryview.BinaryView, name: types.QualifiedNameType, line_width = 80, collapsed = False, escaping: TokenEscapingType = TokenEscapingType.BackticksTokenEscapingType) -> List[types.TypeDefinitionLine]: + def get_type_lines(self, type: types.Type, container: 'typecontainer.TypeContainer', name: types.QualifiedNameType, line_width = 80, collapsed = False, escaping: TokenEscapingType = TokenEscapingType.BackticksTokenEscapingType) -> List[types.TypeDefinitionLine]: """ Generate a multi-line representation of a type :param type: Type to print - :param data: Binary View in which the type is defined + :param container: Type Container containing the type and dependencies :param name: Name of the type :param line_width: Maximum width of lines, in characters :param collapsed: Whether to collapse structure/enum blocks @@ -488,31 +489,20 @@ class CoreTypePrinter(TypePrinter): core.free_string(result_cpp) return result - def get_type_lines(self, type: types.Type, data: binaryview.BinaryView, - name: types.QualifiedNameType, line_width = 80, collapsed = False, + def get_type_lines(self, type: types.Type, container: 'typecontainer.TypeContainer', + name: types.QualifiedNameType, + line_width = 80, collapsed = False, escaping: TokenEscapingType = TokenEscapingType.BackticksTokenEscapingType ) -> List[types.TypeDefinitionLine]: if not isinstance(name, types.QualifiedName): name = types.QualifiedName(name) count = ctypes.c_ulonglong() core_lines = ctypes.POINTER(core.BNTypeDefinitionLine)() - if not core.BNGetTypePrinterTypeLines(self.handle, type.handle, data.handle, name._to_core_struct(), line_width, collapsed, ctypes.c_int(escaping), core_lines, count): + if not core.BNGetTypePrinterTypeLines(self.handle, type.handle, container.handle, name._to_core_struct(), line_width, collapsed, ctypes.c_int(escaping), core_lines, count): raise RuntimeError("BNGetTypePrinterTypeLines returned False") lines = [] for i in range(count.value): - tokens = _function.InstructionTextToken._from_core_struct(core_lines[i].tokens, core_lines[i].count) - type_ = types.Type.create(handle=core.BNNewTypeReference(core_lines[i].type), platform=data.platform) - root_type = types.Type.create(handle=core.BNNewTypeReference(core_lines[i].rootType), platform=data.platform) - root_type_name = core.pyNativeStr(core_lines[i].rootTypeName) - if core_lines[i].baseType: - const_conf = types.BoolWithConfidence.get_core_struct(False, 0) - volatile_conf = types.BoolWithConfidence.get_core_struct(False, 0) - handle = core.BNCreateNamedTypeReference(core_lines[i].baseType, 0, 1, const_conf, volatile_conf) - base_type = types.NamedTypeReferenceType(handle, data.platform) - else: - base_type = None - line = types.TypeDefinitionLine(core_lines[i].lineType, tokens, type_, root_type, root_type_name, base_type, - core_lines[i].baseOffset, core_lines[i].offset, core_lines[i].fieldIndex) + line = types.TypeDefinitionLine._from_core_struct(core_lines[i], container.platform) lines.append(line) core.BNFreeTypeDefinitionLineList(core_lines, count.value) return lines diff --git a/python/types.py b/python/types.py index 96532a4d..9fbe7a93 100644 --- a/python/types.py +++ b/python/types.py @@ -37,6 +37,7 @@ from . import variable from . import architecture from . import binaryview from . import platform as _platform +from . import typecontainer from . import typelibrary from . import typeparser @@ -47,7 +48,7 @@ ParamsType = Union[List['Type'], List['FunctionParameter'], List[Tuple[str, 'Typ MembersType = Union[List['StructureMember'], List['Type'], List[Tuple['Type', str]]] EnumMembersType = Union[List[Tuple[str, int]], List[str], List['EnumerationMember']] SomeType = Union['TypeBuilder', 'Type'] -TypeContainer = Union['binaryview.BinaryView', 'typelibrary.TypeLibrary'] +TypeContainerType = Union['binaryview.BinaryView', 'typelibrary.TypeLibrary'] NameSpaceType = Optional[Union[str, List[str], 'NameSpace']] TypeParserResult = typeparser.TypeParserResult # The following are needed to prevent the type checker from getting @@ -515,7 +516,7 @@ class BoolWithConfidence: @dataclass class MutableTypeBuilder(Generic[TB]): type: TB - container: TypeContainer + container: TypeContainerType name: QualifiedName platform: Optional['_platform.Platform'] confidence: int @@ -601,7 +602,7 @@ class TypeBuilder: @classmethod def builder( - cls: typing.Type[TB], container: TypeContainer, name: 'QualifiedName', user: bool = True, platform: Optional['_platform.Platform'] = None, + cls: typing.Type[TB], container: TypeContainerType, name: 'QualifiedName', user: bool = True, platform: Optional['_platform.Platform'] = None, confidence: int = core.max_confidence ) -> 'MutableTypeBuilder[TB]': return MutableTypeBuilder(cls.create(), container, name, platform, confidence, user) @@ -1997,7 +1998,7 @@ class Type: return result def get_lines( - self, bv: 'binaryview.BinaryView', name: str, line_width: int = 80, collapsed: bool = False, + self, bv: Union['binaryview.BinaryView', 'typecontainer.TypeContainer'], name: str, line_width: int = 80, collapsed: bool = False, escaping: TokenEscapingType = TokenEscapingType.NoTokenEscapingType ) -> List['TypeDefinitionLine']: """ @@ -2014,7 +2015,13 @@ class Type: :rtype: :py:class:`TypeDefinitionLine` """ count = ctypes.c_ulonglong() - core_lines = core.BNGetTypeLines(self._handle, bv.handle, name, line_width, collapsed, escaping, count) + if isinstance(bv, (binaryview.BinaryView,)): + container = bv.type_container + elif isinstance(bv, (typecontainer.TypeContainer,)): + container = bv + else: + assert False, "Unexpected type container type" + core_lines = core.BNGetTypeLines(self._handle, container.handle, name, line_width, collapsed, escaping, count) assert core_lines is not None, "core.BNGetTypeLines returned None" lines = [] for i in range(count.value): @@ -2526,10 +2533,17 @@ class StructureType(Type): def type(self) -> StructureVariant: return StructureVariant(core.BNGetStructureType(self.struct_handle)) - def members_including_inherited(self, view: 'binaryview.BinaryView') -> List[InheritedStructureMember]: + def members_including_inherited(self, view: Union['binaryview.BinaryView', 'typecontainer.TypeContainer']) -> List[InheritedStructureMember]: """Returns structure member list, including those inherited by base structures""" count = ctypes.c_ulonglong() - members = core.BNGetStructureMembersIncludingInherited(self.struct_handle, view.handle, count) + if isinstance(view, (binaryview.BinaryView,)): + container = view.type_container + elif isinstance(view, (typecontainer.TypeContainer,)): + container = view + else: + assert False, "Unexpected type container type" + + members = core.BNGetStructureMembersIncludingInherited(self.struct_handle, container.handle, count) assert members is not None, "core.BNGetInheritedStructureMembers returned None" try: result = [] diff --git a/rust/src/types.rs b/rust/src/types.rs index 17bf96ae..5c568142 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -29,6 +29,7 @@ use crate::{ }; use lazy_static::lazy_static; +use std::ptr::null_mut; use std::{ borrow::Cow, collections::HashSet, @@ -1227,10 +1228,11 @@ impl fmt::Debug for Type { if let Ok(lock) = TYPE_DEBUG_BV.lock() { if let Some(bv) = &*lock { let mut count: usize = 0; + let container = unsafe { BNGetAnalysisTypeContainer(bv.handle) }; let lines: *mut BNTypeDefinitionLine = unsafe { BNGetTypeLines( self.handle, - bv.handle, + container, "".as_ptr() as *const c_char, 80, false, @@ -1238,6 +1240,9 @@ impl fmt::Debug for Type { &mut count as *mut usize, ) }; + unsafe { + BNFreeTypeContainer(container); + } if lines.is_null() { return Err(fmt::Error); @@ -2364,7 +2369,7 @@ impl CoreArrayProvider for QualifiedNameAndType { } unsafe impl CoreOwnedArrayProvider for QualifiedNameAndType { unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) { - BNFreeTypeList(raw, count); + BNFreeTypeAndNameList(raw, count); } } diff --git a/suite/api_test.py b/suite/api_test.py index ec63cfb0..7366adad 100644 --- a/suite/api_test.py +++ b/suite/api_test.py @@ -27,6 +27,7 @@ from binaryninja.lowlevelil import * from binaryninja.mediumlevelil import * from binaryninja.highlevelil import * from binaryninja.variable import * +from binaryninja.typecontainer import * from binaryninja.typeparser import * from binaryninja.typeprinter import * import zipfile @@ -1020,8 +1021,8 @@ class TestTypePrinter(unittest.TestCase): escaping: TokenEscapingType) -> str: return f" bottom text" - def get_type_lines(self, type: types.Type, data: binaryview.BinaryView, name: types.QualifiedName, line_width, - collapsed, escaping: TokenEscapingType) -> List[types.TypeDefinitionLine]: + def get_type_lines(self, type: types.Type, container: typecontainer.TypeContainer, name: types.QualifiedName, + line_width, collapsed, escaping: TokenEscapingType) -> List[types.TypeDefinitionLine]: return [ TypeDefinitionLine(TypeDefinitionLineType.TypedefLineType, [ InstructionTextToken(InstructionTextTokenType.TextToken, "the type is: ", 0), @@ -1056,7 +1057,9 @@ class TestTypePrinter(unittest.TestCase): result = tp.get_type_string_after_name(Type.void()) assert result is not None assert result == " bottom text" - result = tp.get_type_lines(Type.void(), BinaryView.new(b''), QualifiedName(['test'])) + bv = BinaryView.new(b'') + bv.platform = Platform['windows-x86_64'] + result = tp.get_type_lines(Type.void(), bv.type_container, QualifiedName(['test']), bv.platform) assert result is not None assert len(result) == 1 assert len(result[0].tokens) == 3 @@ -1199,12 +1199,12 @@ bool Type::AddTypeMemberTokens(BinaryView* data, vector<InstructionTextToken>& t } -std::vector<TypeDefinitionLine> Type::GetLines(Ref<BinaryView> data, const std::string& name, +std::vector<TypeDefinitionLine> Type::GetLines(const TypeContainer& types, const std::string& name, int lineWidth, bool collapsed, BNTokenEscapingType escaping) { size_t count; BNTypeDefinitionLine* list = - BNGetTypeLines(m_object, data->m_object, name.c_str(), lineWidth, collapsed, escaping, &count); + BNGetTypeLines(m_object, types.GetObject(), name.c_str(), lineWidth, collapsed, escaping, &count); std::vector<TypeDefinitionLine> results; for (size_t i = 0; i < count; i++) @@ -2145,10 +2145,10 @@ vector<StructureMember> Structure::GetMembers() const } -vector<InheritedStructureMember> Structure::GetMembersIncludingInherited(BinaryView* view) const +vector<InheritedStructureMember> Structure::GetMembersIncludingInherited(const TypeContainer& types) const { size_t count; - BNInheritedStructureMember* members = BNGetStructureMembersIncludingInherited(m_object, view->GetObject(), &count); + BNInheritedStructureMember* members = BNGetStructureMembersIncludingInherited(m_object, types.GetObject(), &count); vector<InheritedStructureMember> result; result.reserve(count); diff --git a/typecontainer.cpp b/typecontainer.cpp new file mode 100644 index 00000000..d91b8d55 --- /dev/null +++ b/typecontainer.cpp @@ -0,0 +1,406 @@ +// Copyright (c) 2015-2023 Vector 35 Inc +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#include "binaryninjaapi.h" + +using namespace BinaryNinja; + + +TypeContainer::TypeContainer(BNTypeContainer* container): m_object(container) +{ + +} + + +TypeContainer::TypeContainer(TypeContainer&& other) +{ + m_object = std::move(other.m_object); + other.m_object = nullptr; +} + + +TypeContainer::TypeContainer(Ref<BinaryView> data) +{ + auto container = data->GetTypeContainer(); + m_object = BNDuplicateTypeContainer(container.m_object); +} + + +TypeContainer::TypeContainer(Ref<TypeLibrary> library) +{ + auto container = library->GetTypeContainer(); + m_object = BNDuplicateTypeContainer(container.m_object); +} + + +TypeContainer::TypeContainer(Ref<Platform> platform) +{ + auto container = platform->GetTypeContainer(); + m_object = BNDuplicateTypeContainer(container.m_object); +} + + +TypeContainer::~TypeContainer() +{ + if (m_object) + BNFreeTypeContainer(m_object); + m_object = nullptr; +} + + +TypeContainer::TypeContainer(const TypeContainer& other) +{ + m_object = BNDuplicateTypeContainer(other.m_object); +} + + +TypeContainer& TypeContainer::operator=(const TypeContainer& other) +{ + m_object = BNDuplicateTypeContainer(other.m_object); + return *this; +} + + +TypeContainer& TypeContainer::operator=(TypeContainer&& other) +{ + m_object = std::move(other.m_object); + other.m_object = nullptr; + return *this; +} + + +std::string TypeContainer::GetId() const +{ + char* id = BNTypeContainerGetId(m_object); + std::string result = id; + BNFreeString(id); + return result; +} + + +std::string TypeContainer::GetName() const +{ + char* name = BNTypeContainerGetName(m_object); + std::string result = name; + BNFreeString(name); + return result; +} + + +BNTypeContainerType TypeContainer::GetType() const +{ + return BNTypeContainerGetType(m_object); +} + + +bool TypeContainer::IsMutable() const +{ + return BNTypeContainerIsMutable(m_object); +} + + +Ref<Platform> TypeContainer::GetPlatform() const +{ + BNPlatform* platform = BNTypeContainerGetPlatform(m_object); + if (!platform) + return nullptr; + return new Platform(platform); +} + + +std::optional<std::string> TypeContainer::AddType(QualifiedName name, Ref<Type> type) +{ + auto result = AddTypes({std::make_pair(name, type)}); + if (!result.has_value()) + return std::nullopt; + + auto found = result->find(name); + if (found != result->end()) + { + return found->second; + } + return std::nullopt; +} + + +std::optional<std::unordered_map<QualifiedName, std::string>> TypeContainer::AddTypes( + const std::vector<std::pair<QualifiedName, Ref<Type>>>& types, + std::function<bool(size_t, size_t)> progress) +{ + BNQualifiedName* apiTypeNames = new BNQualifiedName[types.size()]; + BNType** apiTypes = new BNType*[types.size()]; + for (size_t i = 0; i < types.size(); i++) + { + apiTypeNames[i] = types[i].first.GetAPIObject(); + apiTypes[i] = types[i].second->GetObject(); + } + + ProgressContext apiProgress; + if (progress) + apiProgress.callback = progress; + else + apiProgress.callback = [](size_t, size_t) { return true; }; + + char** resultIds; + BNQualifiedName* resultNames; + size_t resultCount; + bool success = BNTypeContainerAddTypes(m_object, apiTypeNames, apiTypes, types.size(), ProgressCallback, &apiProgress, &resultNames, &resultIds, &resultCount); + + for (size_t i = 0; i < types.size(); i++) + { + QualifiedName::FreeAPIObject(&apiTypeNames[i]); + } + delete[] apiTypeNames; + delete[] apiTypes; + if (!success) + return {}; + + std::unordered_map<QualifiedName, std::string> result; + for (size_t i = 0; i < resultCount; i++) + { + result[QualifiedName::FromAPIObject(&resultNames[i])] = resultIds[i]; + } + BNFreeStringList(resultIds, resultCount); + BNFreeTypeNameList(resultNames, resultCount); + + return result; +} + + +bool TypeContainer::RenameType(const std::string& typeId, const QualifiedName& newName) +{ + BNQualifiedName apiNewName = newName.GetAPIObject(); + bool success = BNTypeContainerRenameType(m_object, typeId.c_str(), &apiNewName); + QualifiedName::FreeAPIObject(&apiNewName); + return success; +} + + +bool TypeContainer::DeleteType(const std::string& typeId) +{ + return BNTypeContainerDeleteType(m_object, typeId.c_str()); +} + + +std::optional<std::string> TypeContainer::GetTypeId(const QualifiedName& typeName) const +{ + BNQualifiedName apiTypeName = typeName.GetAPIObject(); + char* result; + bool success = BNTypeContainerGetTypeId(m_object, &apiTypeName, &result); + QualifiedName::FreeAPIObject(&apiTypeName); + if (!success) + return {}; + return std::string(result); +} + + +std::optional<QualifiedName> TypeContainer::GetTypeName(const std::string& typeId) const +{ + BNQualifiedName apiResult; + if (!BNTypeContainerGetTypeName(m_object, typeId.c_str(), &apiResult)) + return {}; + QualifiedName result = QualifiedName::FromAPIObject(&apiResult); + BNFreeQualifiedName(&apiResult); + return result; +} + + +std::optional<Ref<Type>> TypeContainer::GetTypeById(const std::string& typeId) const +{ + BNType* apiResult; + if (!BNTypeContainerGetTypeById(m_object, typeId.c_str(), &apiResult)) + return {}; + return new Type(apiResult); +} + + +std::optional<std::unordered_map<std::string, std::pair<QualifiedName, Ref<Type>>>> TypeContainer::GetTypes() const +{ + char** resultIds; + BNQualifiedName* resultNames; + BNType** resultTypes; + size_t resultCount; + if (!BNTypeContainerGetTypes(m_object, &resultIds, &resultNames, &resultTypes, &resultCount)) + return {}; + + std::unordered_map<std::string, std::pair<QualifiedName, Ref<Type>>> result; + for (size_t i = 0; i < resultCount; i++) + { + result[resultIds[i]] = std::make_pair(QualifiedName::FromAPIObject(&resultNames[i]), new Type( + BNNewTypeReference(resultTypes[i]))); + } + BNFreeStringList(resultIds, resultCount); + BNFreeTypeNameList(resultNames, resultCount); + BNFreeTypeList(resultTypes, resultCount); + + return result; +} + + +std::optional<Ref<Type>> TypeContainer::GetTypeByName(const QualifiedName& typeName) const +{ + BNQualifiedName apiTypeName = typeName.GetAPIObject(); + BNType* apiResult; + bool success = BNTypeContainerGetTypeByName(m_object, &apiTypeName, &apiResult); + QualifiedName::FreeAPIObject(&apiTypeName); + if (!success) + return {}; + return new Type(apiResult); +} + + +std::optional<std::unordered_set<std::string>> TypeContainer::GetTypeIds() const +{ + char** resultIds; + size_t resultCount; + if (!BNTypeContainerGetTypeIds(m_object, &resultIds, &resultCount)) + return {}; + + std::unordered_set<std::string> result; + for (size_t i = 0; i < resultCount; i++) + { + result.insert(resultIds[i]); + } + BNFreeStringList(resultIds, resultCount); + + return result; +} + + +std::optional<std::unordered_set<QualifiedName>> TypeContainer::GetTypeNames() const +{ + BNQualifiedName* resultNames; + size_t resultCount; + if (!BNTypeContainerGetTypeNames(m_object, &resultNames, &resultCount)) + return {}; + + std::unordered_set<QualifiedName> result; + for (size_t i = 0; i < resultCount; i++) + { + result.insert(QualifiedName::FromAPIObject(&resultNames[i])); + } + BNFreeTypeNameList(resultNames, resultCount); + + return result; +} + + +std::optional<std::unordered_map<std::string, QualifiedName>> TypeContainer::GetTypeNamesAndIds() const +{ + char** resultIds; + BNQualifiedName* resultNames; + size_t resultCount; + if (!BNTypeContainerGetTypeNamesAndIds(m_object, &resultIds, &resultNames, &resultCount)) + return {}; + + std::unordered_map<std::string, QualifiedName> result; + for (size_t i = 0; i < resultCount; i++) + { + result[resultIds[i]] = QualifiedName::FromAPIObject(&resultNames[i]); + } + BNFreeStringList(resultIds, resultCount); + BNFreeTypeNameList(resultNames, resultCount); + + return result; +} + + +bool TypeContainer::ParseTypesFromSource( + const std::string& text, + const std::string& fileName, + const std::vector<std::string>& options, + const std::vector<std::string>& includeDirs, + const std::string& autoTypeSource, + BinaryNinja::TypeParserResult& result, + std::vector<TypeParserError>& errors +) +{ + const char** apiOptions = new const char*[options.size()]; + for (size_t i = 0; i < options.size(); ++i) + { + apiOptions[i] = options[i].c_str(); + } + const char** apiIncludeDirs = new const char*[includeDirs.size()]; + for (size_t i = 0; i < includeDirs.size(); ++i) + { + apiIncludeDirs[i] = includeDirs[i].c_str(); + } + + BNTypeParserResult apiResult; + BNTypeParserError* apiErrors; + size_t errorCount; + + auto success = BNTypeContainerParseTypesFromSource(m_object, text.c_str(), fileName.c_str(), + apiOptions, options.size(), apiIncludeDirs, includeDirs.size(), autoTypeSource.c_str(), &apiResult, + &apiErrors, &errorCount); + + delete [] apiOptions; + delete [] apiIncludeDirs; + + for (size_t j = 0; j < errorCount; j ++) + { + TypeParserError error; + error.severity = apiErrors[j].severity, + error.message = apiErrors[j].message, + error.fileName = apiErrors[j].fileName, + error.line = apiErrors[j].line, + error.column = apiErrors[j].column, + errors.push_back(error); + } + BNFreeTypeParserErrors(apiErrors, errorCount); + + if (!success) + { + return false; + } + + result.types.clear(); + for (size_t j = 0; j < apiResult.typeCount; ++j) + { + result.types.push_back({ + QualifiedName::FromAPIObject(&apiResult.types[j].name), + new Type(BNNewTypeReference(apiResult.types[j].type)), + apiResult.types[j].isUser + }); + } + + result.variables.clear(); + for (size_t j = 0; j < apiResult.variableCount; ++j) + { + result.variables.push_back({ + QualifiedName::FromAPIObject(&apiResult.variables[j].name), + new Type(BNNewTypeReference(apiResult.variables[j].type)), + apiResult.variables[j].isUser + }); + } + + result.functions.clear(); + for (size_t j = 0; j < apiResult.functionCount; ++j) + { + result.functions.push_back({ + QualifiedName::FromAPIObject(&apiResult.functions[j].name), + new Type(BNNewTypeReference(apiResult.functions[j].type)), + apiResult.functions[j].isUser + }); + } + + BNFreeTypeParserResult(&apiResult); + return true; +} diff --git a/typelibrary.cpp b/typelibrary.cpp index 73db3966..2e7c15d1 100644 --- a/typelibrary.cpp +++ b/typelibrary.cpp @@ -115,6 +115,12 @@ Ref<Metadata> TypeLibrary::QueryMetadata(const std::string& key) } +TypeContainer TypeLibrary::GetTypeContainer() +{ + return TypeContainer(BNGetTypeLibraryTypeContainer(m_object)); +} + + void TypeLibrary::SetGuid(const std::string& guid) { BNSetTypeLibraryGuid(m_object, guid.c_str()); @@ -153,6 +159,7 @@ std::vector<QualifiedNameAndType> TypeLibrary::GetNamedObjects() QualifiedNameAndType qnat; qnat.name = QualifiedName::FromAPIObject(&objects[i].name); qnat.type = new Type(BNNewTypeReference(objects[i].type)); + result.push_back(std::move(qnat)); } BNFreeQualifiedNameAndTypeArray(objects, count); return result; @@ -169,6 +176,7 @@ std::vector<QualifiedNameAndType> TypeLibrary::GetNamedTypes() QualifiedNameAndType qnat; qnat.name = QualifiedName::FromAPIObject(&types[i].name); qnat.type = new Type(BNNewTypeReference(types[i].type)); + result.push_back(std::move(qnat)); } BNFreeQualifiedNameAndTypeArray(types, count); return result; diff --git a/typeprinter.cpp b/typeprinter.cpp index 3242f323..036c7c18 100644 --- a/typeprinter.cpp +++ b/typeprinter.cpp @@ -101,13 +101,13 @@ bool TypePrinter::GetTypeStringAfterNameCallback(void* ctxt, BNType* type, } -bool TypePrinter::GetTypeLinesCallback(void* ctxt, BNType* type, BNBinaryView* data, +bool TypePrinter::GetTypeLinesCallback(void* ctxt, BNType* type, BNTypeContainer* types, BNQualifiedName* name, int lineWidth, bool collapsed, BNTokenEscapingType escaping, BNTypeDefinitionLine** result, size_t* resultCount) { TypePrinter* printer = (TypePrinter*)ctxt; vector<TypeDefinitionLine> lines = printer->GetTypeLines( - new Type(BNNewTypeReference(type)), new BinaryView(BNNewViewReference(data)), + new Type(BNNewTypeReference(type)), TypeContainer(types), QualifiedName::FromAPIObject(name), lineWidth, collapsed, escaping); *resultCount = lines.size(); @@ -433,7 +433,7 @@ std::string CoreTypePrinter::GetTypeStringAfterName(Ref<Type> type, Ref<Platform std::vector<TypeDefinitionLine> CoreTypePrinter::GetTypeLines(Ref<Type> type, - Ref<BinaryView> data, const QualifiedName& name, int lineWidth, + const TypeContainer& types, const QualifiedName& name, int lineWidth, bool collapsed, BNTokenEscapingType escaping) { BNTypeDefinitionLine* lines; @@ -441,7 +441,8 @@ std::vector<TypeDefinitionLine> CoreTypePrinter::GetTypeLines(Ref<Type> type, BNQualifiedName qname = name.GetAPIObject(); - bool success = BNGetTypePrinterTypeLines(GetObject(), type->GetObject(), data->GetObject(), &qname, lineWidth, collapsed, escaping, &lines, &lineCount); + bool success = BNGetTypePrinterTypeLines(GetObject(), type->GetObject(), types.GetObject(), &qname, + lineWidth, collapsed, escaping, &lines, &lineCount); QualifiedName::FreeAPIObject(&qname); if (!success) diff --git a/ui/createtypedialog.h b/ui/createtypedialog.h index 80de6b0b..0802cced 100644 --- a/ui/createtypedialog.h +++ b/ui/createtypedialog.h @@ -18,18 +18,18 @@ class BINARYNINJAUIAPI CreateTypeDialog : public QDialog DialogTextEdit* m_code; QTextEdit* m_errors; - BinaryViewRef m_data; + BinaryNinja::TypeContainer m_container; std::vector<BinaryNinja::ParsedType> m_results; std::set<BinaryNinja::QualifiedName> m_typesAllowRedefinition; public: - CreateTypeDialog(QWidget* parent, BinaryViewRef data, const QString& title, const QString& definition, + CreateTypeDialog(QWidget* parent, const BinaryNinja::TypeContainer& container, const QString& title, const QString& definition, const std::set<BinaryNinja::QualifiedName>& typesAllowRedefinition = {}); - static CreateTypeDialog* createWithType(QWidget* parent, BinaryViewRef data, BinaryNinja::QualifiedName name, TypeRef type); + static CreateTypeDialog* createWithType(QWidget* parent, const BinaryNinja::TypeContainer& container, BinaryNinja::QualifiedName name, TypeRef type); std::vector<BinaryNinja::ParsedType> getResults() { return m_results; } - void applyResults() { applyResultsTo(this, m_data); } - void applyResultsTo(QWidget* parent, BinaryViewRef view); + void applyResults() { applyResultsTo(this, m_container); } + void applyResultsTo(QWidget* parent, BinaryNinja::TypeContainer container); private Q_SLOTS: void createType(); diff --git a/ui/uitypes.h b/ui/uitypes.h index 86707018..bf15cbd6 100644 --- a/ui/uitypes.h +++ b/ui/uitypes.h @@ -69,6 +69,7 @@ typedef BinaryNinja::Ref<BinaryNinja::BinaryData> BinaryDataRef; typedef BinaryNinja::Ref<BinaryNinja::BinaryView> BinaryViewRef; typedef BinaryNinja::Ref<BinaryNinja::BinaryViewType> BinaryViewTypeRef; typedef BinaryNinja::Ref<BinaryNinja::Database> DatabaseRef; +typedef BinaryNinja::Ref<BinaryNinja::DebugInfo> DebugInfoRef; typedef BinaryNinja::Ref<BinaryNinja::DisassemblySettings> DisassemblySettingsRef; typedef BinaryNinja::Ref<BinaryNinja::DownloadInstance> DownloadInstanceRef; typedef BinaryNinja::Ref<BinaryNinja::DownloadProvider> DownloadProviderRef; |
