summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Wagner <rusty.wagner@gmail.com>2023-03-16 19:54:07 -0400
committerRusty Wagner <rusty.wagner@gmail.com>2023-03-30 18:05:12 -0400
commitd811fffd69ffba789b960edd4fa31cc3d3f5905e (patch)
tree09d036bc3cedc4b93f9fc45b77ebf86659ee0aec
parent1113603311856740654617341767562218182618 (diff)
Add support for deriving structures from other structures
-rw-r--r--binaryninjaapi.h75
-rw-r--r--binaryninjacore.h38
-rw-r--r--binaryview.cpp13
-rw-r--r--python/binaryview.py29
-rw-r--r--python/typeprinter.py11
-rw-r--r--python/types.py165
-rw-r--r--type.cpp134
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)
diff --git a/type.cpp b/type.cpp
index d7d2dfe4..12973b2a 100644
--- a/type.cpp
+++ b/type.cpp
@@ -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);