summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Smith <glenn@vector35.com>2023-02-20 21:58:55 -0500
committerGlenn Smith <glenn@vector35.com>2023-11-06 16:10:47 -0500
commit4108964609171327618627477163339656037111 (patch)
tree79f4c6da6394b973cee05cc42b6edd7e2e20909d
parentb270d7ebe1e2a406e1f7f14807987d24b0c4a846 (diff)
Type Containers
-rw-r--r--binaryninjaapi.h103
-rw-r--r--binaryninjacore.h68
-rw-r--r--binaryview.cpp22
-rw-r--r--debuginfo.cpp6
-rw-r--r--platform.cpp12
-rw-r--r--python/__init__.py1
-rw-r--r--python/binaryview.py18
-rw-r--r--python/debuginfo.py5
-rw-r--r--python/platform.py11
-rw-r--r--python/typecontainer.py246
-rw-r--r--python/typelibrary.py12
-rw-r--r--python/typeprinter.py30
-rw-r--r--python/types.py28
-rw-r--r--rust/src/types.rs9
-rw-r--r--suite/api_test.py9
-rw-r--r--type.cpp8
-rw-r--r--typecontainer.cpp406
-rw-r--r--typelibrary.cpp8
-rw-r--r--typeprinter.cpp9
-rw-r--r--ui/createtypedialog.h10
-rw-r--r--ui/uitypes.h1
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
diff --git a/type.cpp b/type.cpp
index fc90faf5..f581770c 100644
--- a/type.cpp
+++ b/type.cpp
@@ -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;