diff options
| author | Rusty Wagner <rusty.wagner@gmail.com> | 2023-03-16 19:54:07 -0400 |
|---|---|---|
| committer | Rusty Wagner <rusty.wagner@gmail.com> | 2023-03-30 18:05:12 -0400 |
| commit | d811fffd69ffba789b960edd4fa31cc3d3f5905e (patch) | |
| tree | 09d036bc3cedc4b93f9fc45b77ebf86659ee0aec | |
| parent | 1113603311856740654617341767562218182618 (diff) | |
Add support for deriving structures from other structures
| -rw-r--r-- | binaryninjaapi.h | 75 | ||||
| -rw-r--r-- | binaryninjacore.h | 38 | ||||
| -rw-r--r-- | binaryview.cpp | 13 | ||||
| -rw-r--r-- | python/binaryview.py | 29 | ||||
| -rw-r--r-- | python/typeprinter.py | 11 | ||||
| -rw-r--r-- | python/types.py | 165 | ||||
| -rw-r--r-- | type.cpp | 134 |
7 files changed, 458 insertions, 7 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 92898ae4..5f2987bf 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2617,12 +2617,16 @@ namespace BinaryNinja { static LinearDisassemblyLine FromAPIObject(BNLinearDisassemblyLine* line); }; + class NamedTypeReference; + struct TypeDefinitionLine { BNTypeDefinitionLineType lineType; std::vector<InstructionTextToken> tokens; Ref<Type> type, rootType; std::string rootTypeName; + Ref<NamedTypeReference> baseType; + uint64_t baseOffset; uint64_t offset; size_t fieldIndex; @@ -2890,7 +2894,6 @@ namespace BinaryNinja { struct PossibleValueSet; class Metadata; class Structure; - class NamedTypeReference; struct ParsedType; struct TypeParserResult; class Component; @@ -3841,6 +3844,16 @@ namespace BinaryNinja { */ std::vector<uint64_t> GetDataReferencesForTypeField(const QualifiedName& type, uint64_t offset); + /*! Returns a list of virtual addresses of data which are referenced from the type \c type . + + Only data referenced by structures with the \c __data_var_refs attribute are included. + + \param type QualifiedName of the type + \param offset Offset of the field, relative to the start of the type + \return List of addresses referenced from the type field + */ + std::vector<uint64_t> GetDataReferencesFromForTypeField(const QualifiedName& type, uint64_t offset); + /*! Returns a list of type references to a specific type field \param type QualifiedName of the type @@ -7440,6 +7453,29 @@ namespace BinaryNinja { BNMemberScope scope; }; + /*! + \ingroup types + */ + struct InheritedStructureMember + { + Ref<NamedTypeReference> base; + uint64_t baseOffset; + StructureMember member; + size_t memberIndex; + }; + + /*! + \ingroup types + */ + struct BaseStructure + { + Ref<NamedTypeReference> type; + uint64_t offset, width; + + BaseStructure(NamedTypeReference* type, uint64_t offset, uint64_t width); + BaseStructure(Type* type, uint64_t offset); + }; + /*! Structure is a class that wraps built structures and retrieves info about them. \see StructureBuilder is used for building structures @@ -7450,12 +7486,25 @@ namespace BinaryNinja { public: Structure(BNStructure* s); - /*! Get a list of Structure members + /*! Get a list of base structures. Offsets that are not defined by this structure will be filled + in by the fields of the base structure(s). + + \return The list of base structures + */ + std::vector<BaseStructure> GetBaseStructures() const; + + /*! Get a list of Structure members, excluding those inherited from base structures \return The list of structure members */ std::vector<StructureMember> GetMembers() const; + /*! Get a list of Structure members, including those inherited from base structures + + \return The list of structure members + */ + std::vector<InheritedStructureMember> GetMembersIncludingInherited(BinaryView* view) const; + /*! Get a structure member by name \param name Name of the member to retrieve @@ -7487,6 +7536,15 @@ namespace BinaryNinja { */ uint64_t GetWidth() const; + /*! Get the structure pointer offset in bytes. Pointers to this structure will implicitly + have this offset subtracted from the pointer to arrive at the start of the structure. + Effectively, the pointer offset becomes the new start of the structure, and fields + before it are accessed using negative offsets from the pointer. + + \return The structure pointer offset in bytes + */ + int64_t GetPointerOffset() const; + /*! Get the structure alignment \return The structure alignment @@ -7505,6 +7563,12 @@ namespace BinaryNinja { */ bool IsUnion() const; + /*! Whether structure field references propagate the references to data variable field values + + \return Whether the structure propagates data variable references + */ + bool PropagateDataVariableReferences() const; + /*! Get the structure type \return The structure type @@ -7557,6 +7621,9 @@ namespace BinaryNinja { */ Ref<Structure> Finalize() const; + std::vector<BaseStructure> GetBaseStructures() const; + StructureBuilder& SetBaseStructures(const std::vector<BaseStructure>& bases); + /*! GetMembers returns a list of structure members \return vector of StructureMember objects @@ -7574,11 +7641,15 @@ namespace BinaryNinja { bool GetMemberAtOffset(int64_t offset, StructureMember& result, size_t& idx) const; uint64_t GetWidth() const; StructureBuilder& SetWidth(size_t width); + int64_t GetPointerOffset() const; + StructureBuilder& SetPointerOffset(int64_t offset); size_t GetAlignment() const; StructureBuilder& SetAlignment(size_t align); bool IsPacked() const; StructureBuilder& SetPacked(bool packed); bool IsUnion() const; + bool PropagateDataVariableReferences() const; + StructureBuilder& SetPropagateDataVariableReferences(bool value); /*! Set the structure type diff --git a/binaryninjacore.h b/binaryninjacore.h index 3e0f4f06..ce9ec90f 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -43,7 +43,7 @@ // 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 33 +#define BN_MINIMUM_CORE_ABI_VERSION 34 #ifdef __GNUC__ #ifdef BINARYNINJACORE_LIBRARY @@ -349,6 +349,8 @@ extern "C" UnknownMemoryToken = 34, EnumerationMemberToken = 35, OperationToken = 36, + BaseStructureNameToken = 37, + BaseStructureSeparatorToken = 38, // The following are output by the analysis system automatically, these should // not be used directly by the architecture plugins CodeSymbolToken = 64, @@ -1621,6 +1623,8 @@ extern "C" BNType* type; BNType* rootType; char* rootTypeName; + BNNamedTypeReference* baseType; + uint64_t baseOffset; uint64_t offset; size_t fieldIndex; }; @@ -1792,6 +1796,7 @@ extern "C" GotoLabelColor, CommentColor, OperationColor, + BaseStructureNameColor, // Script console colors ScriptConsoleOutputColor, @@ -2098,6 +2103,21 @@ extern "C" BNMemberScope scope; }; + struct BNInheritedStructureMember + { + BNNamedTypeReference* base; + uint64_t baseOffset; + BNStructureMember member; + size_t memberIndex; + }; + + struct BNBaseStructure + { + BNNamedTypeReference* type; + uint64_t offset; + uint64_t width; + }; + struct BNEnumerationMember { char* name; @@ -4038,6 +4058,8 @@ extern "C" BNBinaryView* view, BNQualifiedName* type, uint64_t offset, size_t* count); BINARYNINJACOREAPI uint64_t* BNGetDataReferencesForTypeField( BNBinaryView* view, BNQualifiedName* type, uint64_t offset, size_t* count); + BINARYNINJACOREAPI uint64_t* BNGetDataReferencesFromForTypeField( + BNBinaryView* view, BNQualifiedName* type, uint64_t offset, size_t* count); BINARYNINJACOREAPI BNTypeReferenceSource* BNGetTypeReferencesForTypeField( BNBinaryView* view, BNQualifiedName* type, uint64_t offset, size_t* count); @@ -5465,11 +5487,18 @@ extern "C" BINARYNINJACOREAPI void BNFreeStructureMember(BNStructureMember* s); 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); + BINARYNINJACOREAPI void BNFreeInheritedStructureMemberList(BNInheritedStructureMember* members, size_t count); BINARYNINJACOREAPI uint64_t BNGetStructureWidth(BNStructure* s); + BINARYNINJACOREAPI int64_t BNGetStructurePointerOffset(BNStructure* s); BINARYNINJACOREAPI size_t BNGetStructureAlignment(BNStructure* s); BINARYNINJACOREAPI bool BNIsStructurePacked(BNStructure* s); BINARYNINJACOREAPI bool BNIsStructureUnion(BNStructure* s); + BINARYNINJACOREAPI bool BNStructurePropagatesDataVariableReferences(BNStructure* s); BINARYNINJACOREAPI BNStructureVariant BNGetStructureType(BNStructure* s); + BINARYNINJACOREAPI BNBaseStructure* BNGetBaseStructuresForStructure(BNStructure* s, size_t* count); + BINARYNINJACOREAPI void BNFreeBaseStructureList(BNBaseStructure* bases, size_t count); BINARYNINJACOREAPI BNStructure* BNStructureWithReplacedStructure( BNStructure* s, BNStructure* from, BNStructure* to); @@ -5484,13 +5513,20 @@ extern "C" BINARYNINJACOREAPI BNStructureMember* BNGetStructureBuilderMembers(BNStructureBuilder* s, size_t* count); BINARYNINJACOREAPI uint64_t BNGetStructureBuilderWidth(BNStructureBuilder* s); BINARYNINJACOREAPI void BNSetStructureBuilderWidth(BNStructureBuilder* s, uint64_t width); + BINARYNINJACOREAPI int64_t BNGetStructureBuilderPointerOffset(BNStructureBuilder* s); + BINARYNINJACOREAPI void BNSetStructureBuilderPointerOffset(BNStructureBuilder* s, int64_t offset); BINARYNINJACOREAPI size_t BNGetStructureBuilderAlignment(BNStructureBuilder* s); BINARYNINJACOREAPI void BNSetStructureBuilderAlignment(BNStructureBuilder* s, size_t align); BINARYNINJACOREAPI bool BNIsStructureBuilderPacked(BNStructureBuilder* s); BINARYNINJACOREAPI void BNSetStructureBuilderPacked(BNStructureBuilder* s, bool packed); BINARYNINJACOREAPI bool BNIsStructureBuilderUnion(BNStructureBuilder* s); BINARYNINJACOREAPI void BNSetStructureBuilderType(BNStructureBuilder* s, BNStructureVariant type); + BINARYNINJACOREAPI bool BNStructureBuilderPropagatesDataVariableReferences(BNStructureBuilder* s); + BINARYNINJACOREAPI void BNSetStructureBuilderPropagatesDataVariableReferences(BNStructureBuilder* s, bool value); BINARYNINJACOREAPI BNStructureVariant BNGetStructureBuilderType(BNStructureBuilder* s); + BINARYNINJACOREAPI BNBaseStructure* BNGetBaseStructuresForStructureBuilder(BNStructureBuilder* s, size_t* count); + BINARYNINJACOREAPI void BNSetBaseStructuresForStructureBuilder( + BNStructureBuilder* s, BNBaseStructure* bases, size_t count); BINARYNINJACOREAPI void BNAddStructureBuilderMember(BNStructureBuilder* s, const BNTypeWithConfidence* const type, const char* name, BNMemberAccess access, BNMemberScope scope); diff --git a/binaryview.cpp b/binaryview.cpp index 67fe011c..be4c4ca7 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -2199,6 +2199,19 @@ vector<uint64_t> BinaryView::GetDataReferencesForTypeField(const QualifiedName& } +vector<uint64_t> BinaryView::GetDataReferencesFromForTypeField(const QualifiedName& type, uint64_t offset) +{ + size_t count; + BNQualifiedName nameObj = type.GetAPIObject(); + uint64_t* refs = BNGetDataReferencesFromForTypeField(m_object, &nameObj, offset, &count); + QualifiedName::FreeAPIObject(&nameObj); + + vector<uint64_t> result(refs, &refs[count]); + BNFreeDataReferences(refs); + return result; +} + + vector<TypeReferenceSource> BinaryView::GetTypeReferencesForTypeField(const QualifiedName& type, uint64_t offset) { size_t count; diff --git a/python/binaryview.py b/python/binaryview.py index 5c198986..3d2acbdb 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -4488,6 +4488,35 @@ class BinaryView: finally: core.BNFreeDataReferences(refs) + def get_data_refs_from_for_type_field(self, name: '_types.QualifiedNameType', offset: int) -> List[int]: + """ + ``get_data_refs_from_for_type_field`` returns a list of virtual addresses of data which are referenced by the type ``name``. + + Only data referenced by structures with the ``__data_var_refs`` attribute are included. + + :param QualifiedName name: name of type to query for references + :param int offset: offset of the field, relative to the type + :return: list of integers + :rtype: list(integer) + :Example: + + >>> bv.get_data_refs_from_for_type_field('A', 0x8) + [4203812] + >>> + """ + count = ctypes.c_ulonglong(0) + _name = _types.QualifiedName(name)._to_core_struct() + refs = core.BNGetDataReferencesFromForTypeField(self.handle, _name, offset, count) + assert refs is not None, "core.BNGetDataReferencesFromForTypeField returned None" + + result = [] + try: + for i in range(0, count.value): + result.append(refs[i]) + return result + finally: + core.BNFreeDataReferences(refs) + def get_type_refs_for_type(self, name: '_types.QualifiedNameType') -> List['_types.TypeReferenceSource']: """ ``get_type_refs_for_type`` returns a list of TypeReferenceSource objects (xrefs or cross-references) that reference the provided QualifiedName. diff --git a/python/typeprinter.py b/python/typeprinter.py index 3ad1e9f2..2177ba40 100644 --- a/python/typeprinter.py +++ b/python/typeprinter.py @@ -504,8 +504,15 @@ class CoreTypePrinter(TypePrinter): 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) - line = types.TypeDefinitionLine(core_lines[i].lineType, tokens, type_, root_type, root_type_name, - core_lines[i].offset, core_lines[i].fieldIndex) + 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) lines.append(line) core.BNFreeTypeDefinitionLineList(core_lines, count.value) return lines diff --git a/python/types.py b/python/types.py index 5c480127..ee47c841 100644 --- a/python/types.py +++ b/python/types.py @@ -220,6 +220,8 @@ class TypeDefinitionLine: type: 'Type' root_type: 'Type' root_type_name: str + base_type: Optional['NamedTypeReferenceType'] + base_offset: int offset: int field_index: int @@ -235,8 +237,15 @@ class TypeDefinitionLine: type_ = Type.create(handle=core.BNNewTypeReference(struct.type), platform=platform) root_type = Type.create(handle=core.BNNewTypeReference(struct.rootType), platform=platform) root_type_name = core.pyNativeStr(struct.rootTypeName) - return TypeDefinitionLine(struct.lineType, tokens, type_, root_type, root_type_name, - struct.offset, struct.fieldIndex) + if struct.baseType: + const_conf = BoolWithConfidence.get_core_struct(False, 0) + volatile_conf = BoolWithConfidence.get_core_struct(False, 0) + handle = core.BNCreateNamedTypeReference(struct.baseType, 0, 1, const_conf, volatile_conf) + base_type = NamedTypeReferenceType(handle, platform) + else: + base_type = None + return TypeDefinitionLine(struct.lineType, tokens, type_, root_type, root_type_name, base_type, + struct.baseOffset, struct.offset, struct.fieldIndex) def _to_core_struct(self): struct = core.BNTypeDefinitionLine() @@ -246,6 +255,11 @@ class TypeDefinitionLine: struct.type = core.BNNewTypeReference(self.type.handle) struct.rootType = core.BNNewTypeReference(self.root_type.handle) struct.rootTypeName = self.root_type_name + if self.base_type is None: + struct.baseType = None + else: + struct.baseType = core.BNNewNamedTypeReference(self.base_type.ntr_handle) + struct.baseOffset = self.base_offset struct.offset = self.offset struct.fieldIndex = self.field_index return struct @@ -1151,6 +1165,56 @@ class StructureMember: return len(self.type) +@dataclass +class InheritedStructureMember: + base: 'NamedTypeReferenceType' + base_offset: int + member: StructureMember + member_index: int + + def __repr__(self): + if self.base is None: + return f"<member index {self.member_index}: {repr(self.member)}>" + return f"<inherited from {self.base.name} @ {self.base_offset:#x} index {self.member_index}: {repr(self.member)}>" + + def __len__(self): + return len(self.member.type) + + +@dataclass +class BaseStructure: + type: 'NamedTypeReferenceType' + offset: int + width: int + + def __init__(self, type: Union['NamedTypeReferenceType', 'StructureType'], offset: int, width: int = 0): + if isinstance(type, StructureType): + self.type = type.registered_name + self.offset = offset + self.width = type.width + else: + self.type = type + self.offset = offset + self.width = width + + def __repr__(self): + return f"<base: {repr(self.type)}, offset {self.offset:#x}, width: {self.width:#x}>" + + def _to_core_struct(self): + result = core.BNBaseStructure() + result.type = self.type.ntr_handle + result.offset = self.offset + result.width = self.width + return result + + @staticmethod + def _from_core_struct(core_obj: core.BNBaseStructure, platform: Optional['_platform.Platform'] = None): + const_conf = BoolWithConfidence.get_core_struct(False, 0) + volatile_conf = BoolWithConfidence.get_core_struct(False, 0) + handle = core.BNCreateNamedTypeReference(core_obj.type, 0, 1, const_conf, volatile_conf) + return BaseStructure(NamedTypeReferenceType(handle, platform), core_obj.offset, core_obj.width) + + class StructureBuilder(TypeBuilder): def __init__( self, handle: core.BNTypeBuilderHandle, builder_handle: core.BNStructureBuilderHandle, @@ -1237,6 +1301,27 @@ class StructureBuilder(TypeBuilder): self._add_members(members) @property + def base_structures(self) -> List[BaseStructure]: + """Base structure list. Offsets that are not defined by this structure will be filled + in by the fields of the base structure(s).""" + count = ctypes.c_ulonglong() + bases = core.BNGetBaseStructuresForStructureBuilder(self.builder_handle, count) + try: + result = [] + for i in range(0, count.value): + result.append(BaseStructure._from_core_struct(bases[i], self.platform)) + return result + finally: + core.BNFreeBaseStructureList(bases, count.value) + + @base_structures.setter + def base_structures(self, value: List[BaseStructure]) -> None: + bases = (core.BNBaseStructure * len(value))() + for i in range(0, len(value)): + bases[i] = value[i]._to_core_struct() + core.BNSetBaseStructuresForStructureBuilder(self.builder_handle, bases, len(value)) + + @property def packed(self) -> bool: return core.BNIsStructureBuilderPacked(self.builder_handle) @@ -1261,10 +1346,26 @@ class StructureBuilder(TypeBuilder): core.BNSetStructureBuilderWidth(self.builder_handle, value) @property + def pointer_offset(self) -> int: + return core.BNGetStructureBuilderPointerOffset(self.builder_handle) + + @pointer_offset.setter + def pointer_offset(self, value: int) -> None: + core.BNSetStructureBuilderPointerOffset(self.builder_handle, value) + + @property def union(self) -> bool: return core.BNIsStructureBuilderUnion(self.builder_handle) @property + def propagate_data_var_refs(self) -> bool: + return core.BNStructureBuilderPropagatesDataVariableReferences(self.builder_handle) + + @propagate_data_var_refs.setter + def propagate_data_var_refs(self, value: bool) -> None: + core.BNSetStructureBuilderPropagatesDataVariableReferences(self.builder_handle, value) + + @property def type(self) -> StructureVariant: return StructureVariant(core.BNGetStructureBuilderType(self.builder_handle)) @@ -2329,11 +2430,35 @@ class StructureType(Type): return result @property + def base_structures(self) -> List[BaseStructure]: + """Base structure list (read-only). Offsets that are not defined by this structure will be filled + in by the fields of the base structure(s).""" + count = ctypes.c_ulonglong() + bases = core.BNGetBaseStructuresForStructure(self.struct_handle, count) + try: + result = [] + for i in range(0, count.value): + result.append(BaseStructure._from_core_struct(bases[i], self.platform)) + return result + finally: + core.BNFreeBaseStructureList(bases, count.value) + + @property def width(self): """Structure width""" return core.BNGetStructureWidth(self.struct_handle) @property + def pointer_offset(self): + """ + Structure pointer offset. Pointers to this structure will implicitly + have this offset subtracted from the pointer to arrive at the start of the structure. + Effectively, the pointer offset becomes the new start of the structure, and fields + before it are accessed using negative offsets from the pointer. + """ + return core.BNGetStructurePointerOffset(self.struct_handle) + + @property def alignment(self): """Structure alignment""" return core.BNGetStructureAlignment(self.struct_handle) @@ -2343,9 +2468,45 @@ class StructureType(Type): return core.BNIsStructurePacked(self.struct_handle) @property + def propagate_data_var_refs(self) -> bool: + """Whether structure field references propagate the references to data variable field values""" + return core.BNStructurePropagatesDataVariableReferences(self.struct_handle) + + @property def type(self) -> StructureVariant: return StructureVariant(core.BNGetStructureType(self.struct_handle)) + def members_including_inherited(self, view: 'binaryview.BinaryView') -> 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) + assert members is not None, "core.BNGetInheritedStructureMembers returned None" + try: + result = [] + for i in range(0, count.value): + if members[i].base: + const_conf = BoolWithConfidence.get_core_struct(False, 0) + volatile_conf = BoolWithConfidence.get_core_struct(False, 0) + handle = core.BNCreateNamedTypeReference(members[i].base, 0, 1, const_conf, volatile_conf) + base_type = NamedTypeReferenceType(handle, self.platform) + else: + base_type = None + result.append( + InheritedStructureMember( + base_type, + members[i].baseOffset, + StructureMember( + Type.create(core.BNNewTypeReference(members[i].member.type), confidence=members[i].member.typeConfidence), + members[i].member.name, members[i].member.offset, MemberAccess(members[i].member.access), + MemberScope(members[i].member.scope) + ), + members[i].memberIndex + ) + ) + finally: + core.BNFreeInheritedStructureMemberList(members, count.value) + return result + def with_replaced_structure(self, from_struct, to_struct) -> 'StructureType': return StructureType( core.BNStructureWithReplacedStructure(self.struct_handle, from_struct.handle, to_struct.handle) @@ -467,6 +467,8 @@ TypeDefinitionLine TypeDefinitionLine::FromAPIObject(BNTypeDefinitionLine* line) result.type = new Type(BNNewTypeReference(line->type)); result.rootType = new Type(BNNewTypeReference(line->rootType)); result.rootTypeName = line->rootTypeName; + result.baseType = line->baseType ? new NamedTypeReference(BNNewNamedTypeReference(line->baseType)) : nullptr; + result.baseOffset = line->baseOffset; result.offset = line->offset; result.fieldIndex = line->fieldIndex; return result; @@ -485,6 +487,8 @@ BNTypeDefinitionLine* TypeDefinitionLine::CreateTypeDefinitionLineList( result[i].type = BNNewTypeReference(lines[i].type->GetObject()); result[i].rootType = BNNewTypeReference(lines[i].rootType->GetObject()); result[i].rootTypeName = BNAllocString(lines[i].rootTypeName.c_str()); + result[i].baseType = lines[i].baseType ? BNNewNamedTypeReference(lines[i].baseType->GetObject()) : nullptr; + result[i].baseOffset = lines[i].baseOffset; result[i].offset = lines[i].offset; result[i].fieldIndex = lines[i].fieldIndex; } @@ -499,12 +503,26 @@ void TypeDefinitionLine::FreeTypeDefinitionLineList(BNTypeDefinitionLine* lines, InstructionTextToken::FreeInstructionTextTokenList(lines[i].tokens, lines[i].count); BNFreeType(lines[i].type); BNFreeType(lines[i].rootType); + BNFreeNamedTypeReference(lines[i].baseType); BNFreeString(lines[i].rootTypeName); } delete[] lines; } +BaseStructure::BaseStructure(NamedTypeReference* _type, uint64_t _offset, uint64_t _width) : + type(_type), offset(_offset), width(_width) +{} + + +BaseStructure::BaseStructure(Type* _type, uint64_t _offset) +{ + type = _type->GetRegisteredName(); + offset = _offset; + width = _type->GetWidth(); +} + + Type::Type(BNType* type) { m_object = type; @@ -1179,6 +1197,8 @@ std::vector<TypeDefinitionLine> Type::GetLines(Ref<BinaryView> data, const std:: line.type = new Type(BNNewTypeReference(list[i].type)); line.rootType = list[i].rootType ? new Type(BNNewTypeReference(list[i].rootType)) : nullptr; line.rootTypeName = list[i].rootTypeName; + line.baseType = list[i].baseType ? new NamedTypeReference(BNNewNamedTypeReference(list[i].baseType)) : nullptr; + line.baseOffset = list[i].baseOffset; line.offset = list[i].offset; line.fieldIndex = list[i].fieldIndex; results.push_back(line); @@ -2042,6 +2062,24 @@ Structure::Structure(BNStructure* s) } +vector<BaseStructure> Structure::GetBaseStructures() const +{ + size_t count; + BNBaseStructure* bases = BNGetBaseStructuresForStructure(m_object, &count); + + vector<BaseStructure> result; + for (size_t i = 0; i < count; i++) + { + BaseStructure base( + new NamedTypeReference(BNNewNamedTypeReference(bases[i].type)), bases[i].offset, bases[i].width); + result.push_back(base); + } + + BNFreeBaseStructureList(bases, count); + return result; +} + + vector<StructureMember> Structure::GetMembers() const { size_t count; @@ -2063,6 +2101,30 @@ vector<StructureMember> Structure::GetMembers() const } +vector<InheritedStructureMember> Structure::GetMembersIncludingInherited(BinaryView* view) const +{ + size_t count; + BNInheritedStructureMember* members = BNGetStructureMembersIncludingInherited(m_object, view->GetObject(), &count); + + vector<InheritedStructureMember> result; + result.reserve(count); + for (size_t i = 0; i < count; i++) + { + InheritedStructureMember member; + member.base = members[i].base ? new NamedTypeReference(BNNewNamedTypeReference(members[i].base)) : nullptr; + member.baseOffset = members[i].baseOffset; + member.member.type = new Type(BNNewTypeReference(members[i].member.type)); + member.member.name = members[i].member.name; + member.member.offset = members[i].member.offset; + member.memberIndex = members[i].memberIndex; + result.push_back(member); + } + + BNFreeInheritedStructureMemberList(members, count); + return result; +} + + bool Structure::GetMemberByName(const string& name, StructureMember& result) const { BNStructureMember* member = BNGetStructureMemberByName(m_object, name.c_str()); @@ -2106,6 +2168,12 @@ uint64_t Structure::GetWidth() const } +int64_t Structure::GetPointerOffset() const +{ + return BNGetStructurePointerOffset(m_object); +} + + size_t Structure::GetAlignment() const { return BNGetStructureAlignment(m_object); @@ -2124,6 +2192,12 @@ bool Structure::IsUnion() const } +bool Structure::PropagateDataVariableReferences() const +{ + return BNStructurePropagatesDataVariableReferences(m_object); +} + + BNStructureVariant Structure::GetStructureType() const { return BNGetStructureType(m_object); @@ -2242,6 +2316,40 @@ Ref<Structure> StructureBuilder::Finalize() const } +vector<BaseStructure> StructureBuilder::GetBaseStructures() const +{ + size_t count; + BNBaseStructure* bases = BNGetBaseStructuresForStructureBuilder(m_object, &count); + + vector<BaseStructure> result; + for (size_t i = 0; i < count; i++) + { + BaseStructure base( + new NamedTypeReference(BNNewNamedTypeReference(bases[i].type)), bases[i].offset, bases[i].width); + result.push_back(base); + } + + BNFreeBaseStructureList(bases, count); + return result; +} + + +StructureBuilder& StructureBuilder::SetBaseStructures(const vector<BaseStructure>& bases) +{ + BNBaseStructure* baseObjs = new BNBaseStructure[bases.size()]; + for (size_t i = 0; i < bases.size(); i++) + { + baseObjs[i].type = bases[i].type->GetObject(); + baseObjs[i].offset = bases[i].offset; + baseObjs[i].width = bases[i].width; + } + + BNSetBaseStructuresForStructureBuilder(m_object, baseObjs, bases.size()); + delete[] baseObjs; + return *this; +} + + vector<StructureMember> StructureBuilder::GetMembers() const { size_t count; @@ -2313,6 +2421,19 @@ StructureBuilder& StructureBuilder::SetWidth(size_t width) } +int64_t StructureBuilder::GetPointerOffset() const +{ + return BNGetStructureBuilderPointerOffset(m_object); +} + + +StructureBuilder& StructureBuilder::SetPointerOffset(int64_t offset) +{ + BNSetStructureBuilderPointerOffset(m_object, offset); + return *this; +} + + size_t StructureBuilder::GetAlignment() const { return BNGetStructureBuilderAlignment(m_object); @@ -2345,6 +2466,19 @@ bool StructureBuilder::IsUnion() const } +bool StructureBuilder::PropagateDataVariableReferences() const +{ + return BNStructureBuilderPropagatesDataVariableReferences(m_object); +} + + +StructureBuilder& StructureBuilder::SetPropagateDataVariableReferences(bool value) +{ + BNSetStructureBuilderPropagatesDataVariableReferences(m_object, value); + return *this; +} + + StructureBuilder& StructureBuilder::SetStructureType(BNStructureVariant t) { BNSetStructureBuilderType(m_object, t); |
