summaryrefslogtreecommitdiff
path: root/python/types.py
diff options
context:
space:
mode:
authorPeter LaFosse <peter@vector35.com>2021-07-07 08:26:29 -0400
committerPeter LaFosse <peter@vector35.com>2021-09-05 10:09:09 -0400
commit764063b2b44dbeba5f2f318c971e4f4acfb48427 (patch)
treee014fe6a859b97a653cef80dc9db66a06c706c37 /python/types.py
parentd376db916f5fc83f9e654edf23364d200839ac50 (diff)
Refactor Python Types
Remove _mutable types
Diffstat (limited to 'python/types.py')
-rw-r--r--python/types.py2212
1 files changed, 1431 insertions, 781 deletions
diff --git a/python/types.py b/python/types.py
index d3f6294d..ddaa5384 100644
--- a/python/types.py
+++ b/python/types.py
@@ -20,19 +20,43 @@
import ctypes
from typing import Generator, List, Union, Mapping, Tuple, Optional
-from dataclasses import dataclass
+from dataclasses import dataclass, field
+import uuid
+from abc import ABC, abstractmethod
# Binary Ninja components
from . import _binaryninjacore as core
-from .enums import SymbolType, SymbolBinding, TypeClass, NamedTypeReferenceClass, StructureType, ReferenceType, VariableSourceType, TypeReferenceType
+from .enums import (StructureVariant, SymbolType, SymbolBinding, TypeClass,
+ NamedTypeReferenceClass, ReferenceType, VariableSourceType, TypeReferenceType, MemberAccess, MemberScope)
from . import callingconvention
-from . import function
+from . import function as _function
from . import variable
from . import architecture
from . import types
+from . import binaryview
+from . import platform as _platform
from . import log
+from . import typelibrary
QualifiedNameType = Union[List[str], str, 'QualifiedName', List[bytes]]
+BoolWithConfidenceType = Union[bool, 'BoolWithConfidence']
+SizeWithConfidenceType = Union[int, 'SizeWithConfidence']
+OffsetWithConfidenceType = Union[int, 'OffsetWithConfidence']
+ParamsType = Union[List['Type'], List['FunctionParameter'], List[Tuple['Type', str]]]
+MembersType = Union[List['StructureMember'], List[Tuple['Type', str]]]
+EnumMembersType = Union[List[Tuple[str,int]], List[str], List['EnumerationMember']]
+SomeType = Union['MutableType', 'Type']
+TypeContainer = Union['binaryview.BinaryView', 'typelibrary.TypeLibrary']
+# The following are needed to prevent the type checker from getting
+# confused as we have member functions in `Type` named the same thing
+_int = int
+_bool = bool
+MemberName = str
+MemberIndex = int
+MemberOffset = int
+
+class TypeCreateException(ValueError):
+ pass
class QualifiedName:
def __init__(self, name:QualifiedNameType=[]):
@@ -139,13 +163,13 @@ class QualifiedName:
self._name = value
+@dataclass(frozen=True)
class TypeReferenceSource:
- def __init__(self, name, offset, ref_type):
- self._name = name
- self._offset = offset
- self._ref_type = ref_type
+ name:QualifiedName
+ offset:int
+ ref_type:TypeReferenceType
- def __str__(self):
+ def __repr__(self):
if self.ref_type == TypeReferenceType.DirectTypeReferenceType:
s = 'direct'
elif self.ref_type == TypeReferenceType.IndirectTypeReferenceType:
@@ -154,70 +178,6 @@ class TypeReferenceSource:
s = 'unknown'
return '<type %s, offset 0x%x, %s>' % (self.name, self.offset, s)
- def __repr__(self):
- return repr(str(self))
-
- @property
- def name(self):
- return self._name
-
- @property
- def offset(self):
- return self._offset
-
- @property
- def ref_type(self):
- return self._ref_type
-
- def __eq__(self, other):
- if isinstance(other, self.__class__):
- return self.name == other.name and self.offset == other.offset and self.ref_type == other.ref_type
- return NotImplemented
-
- def __ne__(self, other):
- if isinstance(other, self.__class__):
- return not self.__eq__(other)
- return NotImplemented
-
- def __lt__(self, other):
- if isinstance(other, self.__class__):
- if self.name < other.name:
- return True
- elif self.name > other.name:
- return False
- elif self.offset < other.offset:
- return True
- elif self.offset > other.offset:
- return False
- return self.ref_type < other.ref_type
- return NotImplemented
-
- def __gt__(self, other):
- if isinstance(other, self.__class__):
- if self.name > other.name:
- return True
- elif self.name < other.name:
- return False
- elif self.offset > other.offset:
- return True
- elif self.offset < other.offset:
- return False
- return self.ref_type > other.ref_type
- return NotImplemented
-
- def __cmp__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
-
- if self == other:
- return 0
- elif self < other:
- return -1
- return 1
-
- def __hash__(self):
- return hash(str(self))
-
class NameSpace(QualifiedName):
def __str__(self):
@@ -278,7 +238,8 @@ class Symbol:
self.handle = _handle
def __del__(self):
- core.BNFreeSymbol(self.handle)
+ if core is not None:
+ core.BNFreeSymbol(self.handle)
def __repr__(self):
return "<%s: \"%s\" @ %#x>" % (self.type, self.full_name, self.address)
@@ -348,16 +309,172 @@ class Symbol:
def auto(self):
return core.BNIsSymbolAutoDefined(self.handle)
-@dataclass(frozen=True)
+
+@dataclass
class FunctionParameter:
- type:'types.Type'
+ type:SomeType
name:str = ""
location:Optional['variable.VariableNameAndType'] = None
def __repr__(self):
if (self.location is not None) and (self.location.name != self.name):
- return "%s %s%s @ %s" % (self.type.get_string_before_name(), self.name, self.type.get_string_after_name(), self.location.name)
- return "%s %s%s" % (self.type.get_string_before_name(), self.name, self.type.get_string_after_name())
+ return "%s %s%s @ %s" % (self.type.immutable_copy().get_string_before_name(), self.name, self.type.immutable_copy().get_string_after_name(), self.location.name)
+ return "%s %s%s" % (self.type.immutable_copy().get_string_before_name(), self.name, self.type.immutable_copy().get_string_after_name())
+
+ def immutable_copy(self) -> 'FunctionParameter':
+ return FunctionParameter(self.type.immutable_copy(), self.name, self.location)
+
+ def mutable_copy(self) -> 'FunctionParameter':
+ return FunctionParameter(self.type.mutable_copy(), self.name, self.location)
+
+
+@dataclass(frozen=True)
+class OffsetWithConfidence:
+ value:int
+ confidence:int=core.max_confidence
+
+ def __int__(self):
+ return self.value
+
+ def to_core_struct(self) -> core.BNOffsetWithConfidence:
+ result = core.BNOffsetWithConfidence()
+ result.value = self.value
+ result.confidence = self.confidence
+ return result
+
+ @classmethod
+ def from_core_struct(cls, core_struct:core.BNOffsetWithConfidence) -> 'OffsetWithConfidence':
+ return cls(core_struct.value, core_struct.confidence)
+
+
+@dataclass(frozen=True)
+class BoolWithConfidence:
+ value:bool
+ confidence:int=core.max_confidence
+
+ def __bool__(self):
+ return self.value
+
+ def to_core_struct(self) -> core.BNBoolWithConfidence:
+ result = core.BNBoolWithConfidence()
+ result.value = self.value
+ result.confidence = self.confidence
+ return result
+
+ @classmethod
+ def from_core_struct(cls, core_struct:core.BNBoolWithConfidence) -> 'BoolWithConfidence':
+ return cls(core_struct.value, core_struct.confidence)
+
+
+@dataclass(frozen=True)
+class MemberAccessWithConfidence:
+ value:MemberAccess
+ confidence:int=core.max_confidence
+
+ def to_core_struct(self) -> core.BNMemberAccessWithConfidence:
+ result = core.BNMemberAccessWithConfidence()
+ result.value = self.value
+ result.confidence = self.confidence
+ return result
+
+ @classmethod
+ def from_core_struct(cls, core_struct:core.BNMemberAccessWithConfidence) -> 'MemberAccessWithConfidence':
+ return cls(core_struct.value, core_struct.confidence)
+
+
+@dataclass(frozen=True)
+class MemberScopeWithConfidence:
+ value:MemberScope
+ confidence:int=core.max_confidence
+
+ def to_core_struct(self) -> core.BNMemberScopeWithConfidence:
+ result = core.BNMemberScopeWithConfidence()
+ result.value = self.value
+ result.confidence = self.confidence
+ return result
+
+ @classmethod
+ def from_core_struct(cls, core_struct:core.BNMemberScopeWithConfidence) -> 'MemberScopeWithConfidence':
+ return cls(core_struct.value, core_struct.confidence)
+
+
+@dataclass(frozen=True)
+class SizeWithConfidence:
+ value:int
+ confidence:int=core.max_confidence
+
+ def __int__(self):
+ return self.value
+
+ def to_core_struct(self) -> core.BNSizeWithConfidence:
+ result = core.BNSizeWithConfidence()
+ result.value = self.value
+ result.confidence = self.confidence
+ return result
+
+ @classmethod
+ def from_core_struct(cls, core_struct:core.BNSizeWithConfidence) -> 'SizeWithConfidence':
+ return cls(core_struct.value, core_struct.confidence)
+
+
+class _TypeBuilder:
+ def __init__(self, handle, **kwargs):
+ assert isinstance(handle.contents, core.BNTypeBuilder), "Attempting to create mutable Type"
+ self.handle = handle
+ core.BNTypeBuilderSetConst(self.handle, kwargs.get("const", BoolWithConfidence(False)).to_core_struct())
+ core.BNTypeBuilderSetVolatile(self.handle, kwargs.get("volatile", BoolWithConfidence(False)).to_core_struct())
+ core.BNSetFunctionTypeBuilderCanReturn(self.handle, kwargs.get("can_return", BoolWithConfidence(False).to_core_struct()))
+ core.BNTypeBuilderSetMemberScope(self.handle, kwargs.get("member_scope", MemberScopeWithConfidence(MemberScope.NoScope).to_core_struct()))
+ core.BNTypeBuilderSetMemberAccess(self.handle, kwargs.get("member_access", MemberAccessWithConfidence(MemberAccess.NoAccess).to_core_struct()))
+
+ def finalize(self):
+ type_handle = core.BNFinalizeTypeBuilder(self.handle)
+ assert type_handle is not None, "core.BNFinalizeTypeBuilder returned None"
+ return type_handle
+
+ @property
+ def const(self) -> BoolWithConfidence:
+ """Whether type is const (read/write)"""
+ result = core.BNIsTypeBuilderConst(self.handle)
+ return BoolWithConfidence(result.value, confidence = result.confidence)
+
+ @const.setter
+ def const(self, value:BoolWithConfidence) -> None:
+ core.BNTypeBuilderSetConst(self.handle, value.to_core_struct())
+
+ @property
+ def volatile(self) -> BoolWithConfidence:
+ """Whether type is volatile (read/write)"""
+ result = core.BNIsTypeBuilderVolatile(self.handle)
+ return BoolWithConfidence(result.value, confidence = result.confidence)
+
+ @volatile.setter
+ def volatile(self, value:BoolWithConfidence) -> None:
+ core.BNTypeBuilderSetVolatile(self.handle, value.to_core_struct())
+
+ @property
+ def can_return(self):
+ core.BNFunctionTypeBuilderCanReturn(self.handle)
+
+ @can_return.setter
+ def can_return(self, value):
+ core.BNSetFunctionTypeBuilderCanReturn(self.handle, value)
+
+ @property
+ def member_scope(self):
+ core.BNTypeBuilderGetMemberScope(self.handle)
+
+ @member_scope.setter
+ def member_scope(self, value):
+ core.BNTypeBuilderSetMemberScope(self.handle, value)
+
+ @property
+ def member_access(self):
+ core.BNTypeBuilderGetMemberAccess(self.handle)
+
+ @member_access.setter
+ def member_access(self, value):
+ core.BNTypeBuilderSetMemberAccess(self.handle, value)
class Type:
@@ -372,33 +489,39 @@ class Type:
:py:meth:`parse_types_from_source_file <binaryninja.platform.Platform.parse_types_from_source_file>`
"""
- def __init__(self, handle, platform = None, confidence = core.max_confidence):
+ def __init__(self, handle, platform:'_platform.Platform'=None, confidence:int=core.max_confidence):
+ assert isinstance(handle.contents, core.BNType), "Attempting to create mutable Type"
self._handle = handle
- self._mutable = isinstance(handle.contents, core.BNTypeBuilder)
self._confidence = confidence
self._platform = platform
+ @classmethod
+ def create(cls, handle, platform:'_platform.Platform'=None, confidence:int=core.max_confidence):
+ type_class = TypeClass(core.BNGetTypeClass(handle))
+ try:
+ return Types[type_class](handle, platform, confidence)
+ except TypeError:
+ assert False, f"{str(type_class)}"
+
def __del__(self):
- if self._mutable:
- core.BNFreeTypeBuilder(self._handle)
- else:
+ if core is not None:
core.BNFreeType(self._handle)
def __repr__(self):
if self._confidence < core.max_confidence:
- return "<type: %s, %d%% confidence>" % (str(self), (self._confidence * 100) // core.max_confidence)
- return "<type: %s>" % str(self)
+ return f"<type: {self}, {self._confidence * 100 // core.max_confidence}% confidence>"
+ return f"<type: {self}>"
def __str__(self):
platform = None
if self._platform is not None:
platform = self._platform.handle
- if self._mutable:
- return core.BNGetTypeBuilderString(self._handle, platform)
- name = self.registered_name
- if (name is not None) and (self.type_class != TypeClass.StructureTypeClass) and (self.type_class != TypeClass.EnumerationTypeClass):
- return self.get_string_before_name() + " " + str(name.name) + self.get_string_after_name()
return core.BNGetTypeString(self._handle, platform)
+ name = None
+ if isinstance(self, RegisteredNameType):
+ name = self.registered_name
+ if (name is not None) and (not isinstance(self, (StructureType, EnumerationType))):
+ return self.get_string_before_name() + " " + str(name.name) + self.get_string_after_name()
def __len__(self):
return self.width
@@ -415,711 +538,606 @@ class Type:
@property
def handle(self):
- if self._mutable:
- # First use of a mutable Type makes it immutable
- finalized = core.BNFinalizeTypeBuilder(self._handle)
- core.BNFreeTypeBuilder(self._handle)
- self._handle = finalized
- self._mutable = False
return self._handle
@property
- def type_class(self):
+ def type_class(self) -> TypeClass:
"""Type class (read-only)"""
- if self._mutable:
- return TypeClass(core.BNGetTypeBuilderClass(self._handle))
return TypeClass(core.BNGetTypeClass(self._handle))
@property
- def width(self):
+ def width(self) -> int:
"""Type width (read-only)"""
- if self._mutable:
- return core.BNGetTypeBuilderWidth(self._handle)
return core.BNGetTypeWidth(self._handle)
@property
- def alignment(self):
+ def alignment(self) -> int:
"""Type alignment (read-only)"""
- if self._mutable:
- return core.BNGetTypeBuilderAlignment(self._handle)
return core.BNGetTypeAlignment(self._handle)
@property
- def signed(self):
- """Whether type is signed (read-only)"""
- if self._mutable:
- result = core.BNIsTypeBuilderSigned(self._handle)
- else:
- result = core.BNIsTypeSigned(self._handle)
- return BoolWithConfidence(result.value, confidence = result.confidence)
-
- @property
- def const(self):
- """Whether type is const (read/write)"""
- if self._mutable:
- result = core.BNIsTypeBuilderConst(self._handle)
- else:
- result = core.BNIsTypeConst(self._handle)
- return BoolWithConfidence(result.value, confidence = result.confidence)
-
- @const.setter
- def const(self, value):
- if not self._mutable:
- raise AttributeError("Finalized Type object is immutable, use mutable_copy()")
- bc = core.BNBoolWithConfidence()
- bc.value = bool(value)
- if hasattr(value, 'confidence'):
- bc.confidence = value.confidence
- else:
- bc.confidence = core.max_confidence
- core.BNTypeBuilderSetConst(self._handle, bc)
-
- @property
- def volatile(self):
- """Whether type is volatile (read/write)"""
- if self._mutable:
- result = core.BNIsTypeBuilderVolatile(self._handle)
- else:
- result = core.BNIsTypeVolatile(self._handle)
- return BoolWithConfidence(result.value, confidence = result.confidence)
-
- @volatile.setter
- def volatile(self, value):
- if not self._mutable:
- raise AttributeError("Finalized Type object is immutable, use mutable_copy()")
- bc = core.BNBoolWithConfidence()
- bc.value = bool(value)
- if hasattr(value, 'confidence'):
- bc.confidence = value.confidence
- else:
- bc.confidence = core.max_confidence
- core.BNTypeBuilderSetVolatile(self._handle, bc)
-
- @property
- def floating_point(self):
- """Whether type is floating point (read-only)"""
- if self._mutable:
- return core.BNIsTypeBuilderFloatingPoint(self._handle)
- return core.BNIsTypeFloatingPoint(self._handle)
-
- @property
- def target(self):
- """Target (read-only)"""
- if self._mutable:
- result = core.BNGetTypeBuilderChildType(self._handle)
- else:
- result = core.BNGetChildType(self._handle)
- if not result.type:
- return None
- return Type(result.type, platform = self._platform, confidence = result.confidence)
-
- @property
- def element_type(self):
- """Target (read-only)"""
- if self._mutable:
- result = core.BNGetTypeBuilderChildType(self._handle)
- else:
- result = core.BNGetChildType(self._handle)
- if not result.type:
- return None
- return Type(result.type, platform = self._platform, confidence = result.confidence)
-
- @property
- def return_value(self):
- """Return value (read-only)"""
- if self._mutable:
- result = core.BNGetTypeBuilderChildType(self._handle)
- else:
- result = core.BNGetChildType(self._handle)
- if not result.type:
- return None
- return Type(result.type, platform = self._platform, confidence = result.confidence)
-
- @property
- def calling_convention(self):
- """Calling convention (read-only)"""
- if self._mutable:
- result = core.BNGetTypeBuilderCallingConvention(self._handle)
- else:
- result = core.BNGetTypeCallingConvention(self._handle)
- if not result.convention:
- return None
- return callingconvention.CallingConvention(None, handle = result.convention, confidence = result.confidence)
-
- @property
- def parameters(self):
- """Type parameters list (read-only)"""
- count = ctypes.c_ulonglong()
- if self._mutable:
- params = core.BNGetTypeBuilderParameters(self._handle, count)
- assert params is not None, "core.BNGetTypeBuilderParameters returned None"
- else:
- params = core.BNGetTypeParameters(self._handle, count)
- assert params is not None, "core.BNGetTypeParameters returned None"
- result = []
- for i in range(0, count.value):
- param_type = Type(core.BNNewTypeReference(params[i].type), platform = self._platform, confidence = params[i].typeConfidence)
- if params[i].defaultLocation:
- param_location = None
- else:
- name = params[i].name
- if (params[i].location.type == VariableSourceType.RegisterVariableSourceType) and (self._platform is not None):
- name = self._platform.arch.get_reg_name(params[i].location.storage)
- elif params[i].location.type == VariableSourceType.StackVariableSourceType:
- name = "arg_%x" % params[i].location.storage
- param_location = variable.VariableNameAndType(params[i].location.type, params[i].location.index,
- params[i].location.storage, name, param_type)
- result.append(FunctionParameter(param_type, params[i].name, param_location))
- core.BNFreeTypeParameterList(params, count.value)
- return result
-
- @property
- def has_variable_arguments(self):
- """Whether type has variable arguments (read-only)"""
- if self._mutable:
- result = core.BNTypeBuilderHasVariableArguments(self._handle)
- else:
- result = core.BNTypeHasVariableArguments(self._handle)
- return BoolWithConfidence(result.value, confidence = result.confidence)
-
- @property
- def can_return(self):
- """Whether type can return"""
- if self._mutable:
- result = core.BNFunctionTypeBuilderCanReturn(self._handle)
- else:
- result = core.BNFunctionTypeCanReturn(self._handle)
- return BoolWithConfidence(result.value, confidence = result.confidence)
-
- @can_return.setter
- def can_return(self, value):
- """Whether type can return (read-only)"""
- if not self._mutable:
- raise AttributeError("Finalized Type object is immutable, use mutable_copy()")
- bc = core.BNBoolWithConfidence()
- bc.value = bool(value)
- if hasattr(value, 'confidence'):
- bc.confidence = value.confidence
- else:
- bc.confidence = core.max_confidence
- core.BNSetFunctionTypeBuilderCanReturn(self._handle, bc)
-
- @property
- def structure(self):
- """Structure of the type (read-only)"""
- if self._mutable:
- result = core.BNGetTypeBuilderStructure(self._handle)
- else:
- result = core.BNGetTypeStructure(self._handle)
- if result is None:
- return None
- return Structure(result)
-
- @property
- def enumeration(self):
- """Type enumeration (read-only)"""
- if self._mutable:
- result = core.BNGetTypeBuilderEnumeration(self._handle)
- else:
- result = core.BNGetTypeEnumeration(self._handle)
- if result is None:
- return None
- return Enumeration(result)
-
- @property
- def named_type_reference(self):
- """Reference to a named type (read-only)"""
- if self._mutable:
- result = core.BNGetTypeBuilderNamedTypeReference(self._handle)
- else:
- result = core.BNGetTypeNamedTypeReference(self._handle)
- if result is None:
- return None
- return NamedTypeReference(handle = result)
-
- @property
- def count(self):
- """Type count (read-only)"""
- if self._mutable:
- return core.BNGetTypeBuilderElementCount(self._handle)
- return core.BNGetTypeElementCount(self._handle)
-
- @property
- def offset(self):
+ def offset(self) -> int:
"""Offset into structure (read-only)"""
- if self._mutable:
- return core.BNGetTypeBuilderOffset(self._handle)
return core.BNGetTypeOffset(self._handle)
@property
- def stack_adjustment(self):
- """Stack adjustment for function (read-only)"""
- if self._mutable:
- result = core.BNGetTypeBuilderStackAdjustment(self._handle)
- else:
- result = core.BNGetTypeStackAdjustment(self._handle)
- return SizeWithConfidence(result.value, confidence = result.confidence)
+ def altname(self) -> str:
+ """Alternative name for the type object"""
+ return core.BNGetTypeAlternateName(self._handle)
- @property
- def registered_name(self):
- """Name of type registered to binary view, if any (read-only)"""
- if self._mutable:
- return None
- name = core.BNGetRegisteredTypeName(self._handle)
- if not name:
- return None
- return NamedTypeReference(handle = name)
+ def to_core_struct(self) -> core.BNTypeWithConfidence:
+ type_conf = core.BNTypeWithConfidence()
+ type_conf.type = self.handle
+ type_conf.confidence = self.confidence
+ return type_conf
- def get_string_before_name(self):
+ def get_string_before_name(self) -> str:
platform = None
if self._platform is not None:
platform = self._platform.handle
- if self._mutable:
- return core.BNGetTypeBuilderStringBeforeName(self._handle, platform)
return core.BNGetTypeStringBeforeName(self._handle, platform)
- def get_string_after_name(self):
+ def get_string_after_name(self) -> str:
platform = None
if self._platform is not None:
platform = self._platform.handle
- if self._mutable:
- return core.BNGetTypeBuilderStringAfterName(self._handle, platform)
return core.BNGetTypeStringAfterName(self._handle, platform)
@property
- def tokens(self):
+ def tokens(self) -> List['_function.InstructionTextToken']:
"""Type string as a list of tokens (read-only)"""
return self.get_tokens()
- def get_tokens(self, base_confidence = core.max_confidence):
+ def get_tokens(self, base_confidence = core.max_confidence) -> List['_function.InstructionTextToken']:
count = ctypes.c_ulonglong()
platform = None
if self._platform is not None:
platform = self._platform.handle
- if self._mutable:
- tokens = core.BNGetTypeBuilderTokens(self._handle, platform, base_confidence, count)
- assert tokens is not None, "core.BNGetTypeBuilderTokens returned None"
- else:
- tokens = core.BNGetTypeTokens(self._handle, platform, base_confidence, count)
- assert tokens is not None, "core.BNGetTypeTokens returned None"
+ tokens = core.BNGetTypeTokens(self._handle, platform, base_confidence, count)
+ assert tokens is not None, "core.BNGetTypeTokens returned None"
- result = function.InstructionTextToken._from_core_struct(tokens, count.value)
+ result = _function.InstructionTextToken._from_core_struct(tokens, count.value)
core.BNFreeInstructionText(tokens, count.value)
return result
- def get_tokens_before_name(self, base_confidence = core.max_confidence):
+ def get_tokens_before_name(self, base_confidence = core.max_confidence) -> List['_function.InstructionTextToken']:
count = ctypes.c_ulonglong()
platform = None
if self._platform is not None:
platform = self._platform.handle
- if self._mutable:
- tokens = core.BNGetTypeBuilderTokensBeforeName(self._handle, platform, base_confidence, count)
- assert tokens is not None, "core.BNGetTypeBuilderTokensBeforeName returned None"
- else:
- tokens = core.BNGetTypeTokensBeforeName(self._handle, platform, base_confidence, count)
- assert tokens is not None, "core.BNGetTypeTokensBeforeName returned None"
- result = function.InstructionTextToken._from_core_struct(tokens, count.value)
+ tokens = core.BNGetTypeTokensBeforeName(self._handle, platform, base_confidence, count)
+ assert tokens is not None, "core.BNGetTypeTokensBeforeName returned None"
+ result = _function.InstructionTextToken._from_core_struct(tokens, count.value)
core.BNFreeInstructionText(tokens, count.value)
return result
- def get_tokens_after_name(self, base_confidence = core.max_confidence):
+ def get_tokens_after_name(self, base_confidence = core.max_confidence) -> List['_function.InstructionTextToken']:
count = ctypes.c_ulonglong()
platform = None
if self._platform is not None:
platform = self._platform.handle
- if self._mutable:
- tokens = core.BNGetTypeBuilderTokensAfterName(self._handle, platform, base_confidence, count)
- assert tokens is not None, "core.BNGetTypeBuilderTokensAfterName returned None"
- else:
- tokens = core.BNGetTypeTokensAfterName(self._handle, platform, base_confidence, count)
- assert tokens is not None, "core.BNGetTypeTokensAfterName returned None"
- result = function.InstructionTextToken._from_core_struct(tokens, count.value)
+ tokens = core.BNGetTypeTokensAfterName(self._handle, platform, base_confidence, count)
+ assert tokens is not None, "core.BNGetTypeTokensAfterName returned None"
+ result = _function.InstructionTextToken._from_core_struct(tokens, count.value)
core.BNFreeInstructionText(tokens, count.value)
return result
+ def with_confidence(self, confidence) -> 'Type':
+ return Type.create(handle = core.BNNewTypeReference(self.handle), platform = self._platform, confidence = confidence)
+
+ @property
+ def confidence(self) -> _int:
+ return self._confidence
+
+ @confidence.setter
+ def confidence(self, value:_int) -> None:
+ self._confidence = value
+
+ @property
+ def platform(self) -> Optional['_platform.Platform']:
+ return self._platform
+
+ @platform.setter
+ def platform(self, value:'_platform.Platform') -> None:
+ self._platform = value
+
+ @abstractmethod
+ def create_mutable(self):
+ raise NotImplementedError("No implementation for create_mutable on base class Type")
+
+ def mutable_copy(self) -> 'MutableType':
+ return self.create_mutable()
+
+ def get_builder(self, bv:'binaryview.BinaryView') -> 'MutableTypeBuilder':
+ t = Types[self.type_class](self._handle).create_mutable()
+ return MutableTypeBuilder(t, bv, self.name, self.platform, self._confidence)
+
+ @staticmethod
+ def builder(bv:'binaryview.BinaryView', name:Optional[QualifiedName]=None, id:Optional[str]=None,
+ platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'MutableTypeBuilder':
+ if name is None and id is None:
+ raise TypeCreateException("Must specify either a name or id to create a builder object")
+ if name is None:
+ t = bv.get_type_by_id(id)
+ if t is None:
+ raise TypeCreateException("failed to look up type by id")
+ registered_name = t.registered_name
+ if registered_name is None:
+ raise TypeCreateException("Registered name for type is None")
+ name = registered_name.name
+ if name is None:
+ raise TypeCreateException("Name for registered name is None")
+ else:
+ t = bv.get_type_by_name(name)
+ if t is None:
+ raise TypeCreateException("failed to look up type by name")
+ return MutableTypeBuilder(t, bv, name, platform, confidence)
+
+ def with_replaced_structure(self, from_struct, to_struct):
+ return Type.create(handle = core.BNTypeWithReplacedStructure(self._handle, from_struct.handle, to_struct.handle))
+
+ def with_replaced_enumeration(self, from_enum, to_enum):
+ return Type.create(handle = core.BNTypeWithReplacedEnumeration(self._handle, from_enum.handle, to_enum.handle))
+
+ def with_replaced_named_type_reference(self, from_ref, to_ref):
+ return Type.create(handle = core.BNTypeWithReplacedNamedTypeReference(self._handle, from_ref.handle, to_ref.handle))
+
@staticmethod
def void():
- return Type(core.BNCreateVoidTypeBuilder())
+ return VoidType.create()
@staticmethod
def bool():
- return Type(core.BNCreateBoolTypeBuilder())
+ return BoolType.create()
@staticmethod
def char():
return Type.int(1, True)
@staticmethod
- def int(width, sign = None, altname=""):
+ def int(width:_int, sign:BoolWithConfidenceType=BoolWithConfidence(True), altname:str="") -> 'IntegerType':
"""
``int`` class method for creating an int Type.
-
:param int width: width of the integer in bytes
:param bool sign: optional variable representing signedness
:param str altname: alternate name for type
"""
- if sign is None:
- sign = BoolWithConfidence(True, confidence = 0)
- elif not isinstance(sign, BoolWithConfidence):
- sign = BoolWithConfidence(sign)
-
- sign_conf = core.BNBoolWithConfidence()
- sign_conf.value = sign.value
- sign_conf.confidence = sign.confidence
-
- return Type(core.BNCreateIntegerTypeBuilder(width, sign_conf, altname))
+ return IntegerType.create(width, sign, altname)
@staticmethod
- def float(width, altname=""):
+ def float(width:_int, altname:str="") -> 'FloatType':
"""
``float`` class method for creating floating point Types.
-
:param int width: width of the floating point number in bytes
:param str altname: alternate name for type
"""
- return Type(core.BNCreateFloatTypeBuilder(width, altname))
+ return FloatType.create(width, altname)
@staticmethod
- def wide_char(width, altname=""):
+ def wide_char(width:_int, altname:str="") -> 'WideCharType':
"""
``wide_char`` class method for creating wide char Types.
-
:param int width: width of the wide character in bytes
:param str altname: alternate name for type
"""
- return Type(core.BNCreateWideCharTypeBuilder(width, altname))
+ return WideCharType.create(width=width, altname=altname)
@staticmethod
- def structure_type(structure_type):
- return Type(core.BNCreateStructureTypeBuilder(structure_type.handle))
+ def structure_type(s:'Structure'):
+ return s.immutable_copy()
@staticmethod
- def named_type(named_type, width = 0, align = 1):
- return Type(core.BNCreateNamedTypeReferenceBuilder(named_type.handle, width, align))
+ def named_type(named_type:'NamedTypeReference') -> 'NamedTypeReferenceType':
+ return named_type.immutable_copy()
@staticmethod
- def named_type_from_type_and_id(type_id, name, t):
- name = QualifiedName(name)._get_core_struct()
- if t is not None:
- t = t.handle
- return Type(core.BNCreateNamedTypeReferenceBuilderFromTypeAndId(type_id, name, t))
+ def named_type_from_type(name:QualifiedName, type:'Type') -> 'NamedTypeReferenceType':
+ return NamedTypeReferenceType.create_from_type(name, type)
@staticmethod
- def named_type_from_type(name, t):
- name = QualifiedName(name)._get_core_struct()
- if t is not None:
- t = t.handle
- return Type(core.BNCreateNamedTypeReferenceBuilderFromTypeAndId("", name, t))
+ def named_type_from_type_and_id(type_id:str, name:QualifiedName, type:'Type') -> 'NamedTypeReferenceType':
+ return NamedTypeReferenceType.create_from_type(name, type, type_id)
- @staticmethod
- def named_type_from_registered_type(view, name):
- name = QualifiedName(name)._get_core_struct()
- return Type(core.BNCreateNamedTypeReferenceBuilderFromType(view.handle, name))
+ def generate_named_type_reference(self, guid:str, name:QualifiedName):
+ return NamedTypeReferenceType.create(NamedTypeReferenceClass.TypedefNamedTypeClass, guid, name)
@staticmethod
- def enumeration_type(arch, e, width=None, sign=False):
- if width is None:
- width = arch.default_int_size
- return Type(core.BNCreateEnumerationTypeBuilder(arch.handle, e.handle, width, sign))
+ def named_type_from_registered_type(view:'binaryview.BinaryView', name:QualifiedName) -> 'NamedTypeReferenceType':
+ return NamedTypeReferenceType.create_from_registered_type(view, name)
@staticmethod
- def pointer(arch, t, const=None, volatile=None, ref_type=None):
- if const is None:
- const = BoolWithConfidence(False, confidence = 0)
- elif not isinstance(const, BoolWithConfidence):
- const = BoolWithConfidence(const)
+ def enumeration_type(arch, e:'Enumeration', width:_int=None, sign:_bool=False) -> 'EnumerationType':
+ return EnumerationType.create(arch, e.members, e.width, e.sign)
- if volatile is None:
- volatile = BoolWithConfidence(False, confidence = 0)
- elif not isinstance(volatile, BoolWithConfidence):
- volatile = BoolWithConfidence(volatile)
-
- if ref_type is None:
- ref_type = ReferenceType.PointerReferenceType
-
- type_conf = core.BNTypeWithConfidence()
- type_conf.type = t.handle
- type_conf.confidence = t.confidence
-
- const_conf = core.BNBoolWithConfidence()
- const_conf.value = const.value
- const_conf.confidence = const.confidence
+ @staticmethod
+ def pointer(type:'Type', arch:'architecture.Architecture'=None,
+ const:BoolWithConfidenceType=BoolWithConfidence(False),
+ volatile:BoolWithConfidenceType=BoolWithConfidence(False),
+ ref_type:ReferenceType=ReferenceType.PointerReferenceType, width:_int=None) -> 'PointerType':
- volatile_conf = core.BNBoolWithConfidence()
- volatile_conf.value = volatile.value
- volatile_conf.confidence = volatile.confidence
+ if arch is not None:
+ width = arch.address_size
+ if width is None:
+ raise TypeCreateException("Must specify either an architecture or a width to create a pointer")
- return Type(core.BNCreatePointerTypeBuilder(arch.handle, type_conf, const_conf, volatile_conf, ref_type))
+ return PointerType.create_with_width(width, type, const, volatile, ref_type)
@staticmethod
- def array(t, count):
- type_conf = core.BNTypeWithConfidence()
- type_conf.type = t.handle
- type_conf.confidence = t.confidence
- return Type(core.BNCreateArrayTypeBuilder(type_conf, count))
+ def array(type:'Type', count:_int) -> 'ArrayType':
+ return ArrayType.create(type, count)
@staticmethod
- def function(ret, params, calling_convention=None, variable_arguments=None, stack_adjust=None):
+ def function(ret:Optional['Type'], params:ParamsType=[], calling_convention:'callingconvention.CallingConvention'=None,
+ variable_arguments:BoolWithConfidenceType=BoolWithConfidence(False),
+ stack_adjust:OffsetWithConfidence=OffsetWithConfidence(0)) -> 'FunctionType':
"""
``function`` class method for creating an function Type.
-
:param Type ret: return Type of the function
:param params: list of parameter Types
:type params: list(Type)
:param CallingConvention calling_convention: optional argument for the function calling convention
:param bool variable_arguments: optional boolean, true if the function has a variable number of arguments
"""
- param_buf = (core.BNFunctionParameter * len(params))()
- for i in range(0, len(params)):
- if isinstance(params[i], Type):
- param_buf[i].name = ""
- param_buf[i].type = params[i].handle
- param_buf[i].typeConfidence = params[i].confidence
- param_buf[i].defaultLocation = True
- elif isinstance(params[i], FunctionParameter):
- param_buf[i].name = params[i].name
- param_buf[i].type = params[i].type.handle
- param_buf[i].typeConfidence = params[i].type.confidence
- if params[i].location is None:
- param_buf[i].defaultLocation = True
- else:
- param_buf[i].defaultLocation = False
- param_buf[i].location.type = params[i].location.source_type
- param_buf[i].location.index = params[i].location.index
- param_buf[i].location.storage = params[i].location.storage
- else:
- param_buf[i].name = params[i][1]
- param_buf[i].type = params[i][0].handle
- param_buf[i].typeConfidence = params[i][0].confidence
- param_buf[i].defaultLocation = True
-
- ret_conf = core.BNTypeWithConfidence()
- ret_conf.type = ret.handle
- ret_conf.confidence = ret.confidence
-
- conv_conf = core.BNCallingConventionWithConfidence()
- if calling_convention is None:
- conv_conf.convention = None
- conv_conf.confidence = 0
- else:
- conv_conf.convention = calling_convention.handle
- conv_conf.confidence = calling_convention.confidence
+ return FunctionType.create(ret, params, calling_convention, variable_arguments, stack_adjust)
- if variable_arguments is None:
- variable_arguments = BoolWithConfidence(False, confidence = 0)
- elif not isinstance(variable_arguments, BoolWithConfidence):
- variable_arguments = BoolWithConfidence(variable_arguments)
+ @staticmethod
+ def from_core_struct(core_type:core.BNType):
+ return Type.create(core.BNNewTypeReference(core_type))
- vararg_conf = core.BNBoolWithConfidence()
- vararg_conf.value = variable_arguments.value
- vararg_conf.confidence = variable_arguments.confidence
+ @staticmethod
+ def structure(members:MembersType=[], packed:_bool=False, type:StructureVariant=StructureVariant.StructStructureType) -> 'StructureType':
+ return StructureType.create(members, packed, type)
- if stack_adjust is None:
- stack_adjust = SizeWithConfidence(0, confidence = 0)
- elif not isinstance(stack_adjust, SizeWithConfidence):
- stack_adjust = SizeWithConfidence(stack_adjust)
+ @staticmethod
+ def enumeration(arch:Optional['architecture.Architecture'], members:EnumMembersType=[],
+ width:Optional[_int]=None, sign:BoolWithConfidenceType=BoolWithConfidence(False)) -> 'EnumerationType':
+ return EnumerationType.create(arch, members, width, sign)
- stack_adjust_conf = core.BNOffsetWithConfidence()
- stack_adjust_conf.value = stack_adjust.value
- stack_adjust_conf.confidence = stack_adjust.confidence
+ @staticmethod
+ def named_type_reference(name:QualifiedName, type:Optional['Type']=None, guid:Optional[str]=None):
+ """
+ Deprecated property kept for backward compability.
+ These operations can now be done directly on the Type object.
+ """
+ return NamedTypeReferenceType.create_from_type(name, type, guid)
- return Type(core.BNCreateFunctionTypeBuilder(ret_conf, conv_conf, param_buf, len(params),
- vararg_conf, stack_adjust_conf))
+ @property
+ @abstractmethod
+ def name(self) -> QualifiedName:
+ raise NotImplementedError("Name not implemented for this type")
@staticmethod
- def generate_auto_type_id(source, name):
- name = QualifiedName(name)._get_core_struct()
- return core.BNGenerateAutoTypeId(source, name)
+ def generate_auto_type_id(source, name:str) -> str:
+ _name = QualifiedName(name)._get_core_struct()
+ return core.BNGenerateAutoTypeId(source, _name)
@staticmethod
- def generate_auto_demangled_type_id(name):
- name = QualifiedName(name)._get_core_struct()
- return core.BNGenerateAutoDemangledTypeId(name)
+ def generate_auto_demangled_type_id(name:str) -> str:
+ _name = QualifiedName(name)._get_core_struct()
+ return core.BNGenerateAutoDemangledTypeId(_name)
@staticmethod
- def get_auto_demangled_type_id_source():
+ def get_auto_demangled_type_id_source() -> str:
return core.BNGetAutoDemangledTypeIdSource()
- def with_confidence(self, confidence):
- return Type(handle = core.BNNewTypeReference(self.handle), platform = self._platform, confidence = confidence)
+ def immutable_copy(self) -> 'Type':
+ return self
- @property
- def confidence(self):
- return self._confidence
- @confidence.setter
- def confidence(self, value):
- self._confidence = value
+@dataclass(frozen=True)
+class RegisterStackAdjustmentWithConfidence:
+ value:int
+ confidence:int=core.max_confidence
+ def __int__(self):
+ return self.value
+
+
+class RegisteredNameType(Type):
@property
- def platform(self):
- return self._platform
+ def registered_name(self) -> Optional['NamedTypeReferenceType']:
+ """Name of type registered to binary view, if any (read-only)"""
+ # assert self.handle is not None, "RegisteredNameType.handle is None"
+ # assert False, f"{str(self.type_class)}"
+ ntr_handle = core.BNGetRegisteredTypeName(self.handle)
+ if ntr_handle is None:
+ return None
+ # assert ntr_handle is not None, "core.BNGetRegisteredTypeName returned None"
+ return NamedTypeReferenceType(self.handle, self.platform, self.confidence, ntr_handle)
- @platform.setter
- def platform(self, value):
- self._platform = value
+ # @property
+ # def name(self) -> Optional[QualifiedName]:
+ # registered_name = self.registered_name
+ # if registered_name is None:
+ # return None
+ # return registered_name.name
- def mutable_copy(self):
- if self._mutable:
- return Type(core.BNDuplicateTypeBuilder(self._handle), confidence = self._confidence)
- return Type(core.BNCreateTypeBuilderFromType(self._handle), confidence = self._confidence)
- def with_replaced_structure(self, from_struct, to_struct):
- return Type(handle = core.BNTypeWithReplacedStructure(self._handle, from_struct.handle, to_struct.handle))
+@dataclass
+class MutableTypeBuilder:
+ type:'MutableType'
+ container:TypeContainer
+ name:QualifiedName
+ platform:Optional['_platform.Platform']
+ confidence:int
+ user:bool = True
- def with_replaced_enumeration(self, from_enum, to_enum):
- return Type(handle = core.BNTypeWithReplacedEnumeration(self._handle, from_enum.handle, to_enum.handle))
+ def __enter__(self):
+ return self.type
- def with_replaced_named_type_reference(self, from_ref, to_ref):
- return Type(handle = core.BNTypeWithReplacedNamedTypeReference(self._handle, from_ref.handle, to_ref.handle))
+ def __exit__(self, type, value, traceback):
+ if isinstance(self.container, binaryview.BinaryView):
+ if self.user:
+ self.container.define_user_type(self.name, self.type.immutable_copy(self.platform, self.confidence))
+ else:
+ type_id = types.Type.generate_auto_type_id(str(uuid.uuid4()), str(self.name))
+ self.container.define_type(type_id, self.name, self.type.immutable_copy(self.platform, self.confidence))
+ else:
+ self.container.add_named_type(self.name, self.type.immutable_copy())
-@dataclass(frozen=True)
-class BoolWithConfidence:
- value:bool
- confidence:int=core.max_confidence
+@dataclass
+class MutableType(ABC):
+ @abstractmethod
+ def immutable_copy(self, platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> Type:
+ return NotImplemented
- def __bool__(self):
- return self.value
+ def builder(self, container:TypeContainer, name:'QualifiedName', user:bool=True, platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> MutableTypeBuilder:
+ return MutableTypeBuilder(self, container, name, platform, confidence, user)
+ @abstractmethod
+ def __len__(self):
+ return NotImplemented
-@dataclass(frozen=True)
-class SizeWithConfidence:
- value:int
- confidence:int=core.max_confidence
+ def mutable_copy(self) -> 'MutableType':
+ return self
- def __int__(self):
- return self.value
+@dataclass
+class CVQualified(MutableType):
+ const:BoolWithConfidence=BoolWithConfidence(False)
+ volatile:BoolWithConfidence=BoolWithConfidence(False)
-@dataclass(frozen=True)
-class RegisterStackAdjustmentWithConfidence:
- value:int
- confidence:int=core.max_confidence
+class CVQualifiedType(Type):
+ @property
+ def const(self):
+ """Whether type is const (read/write)"""
+ result = core.BNIsTypeConst(self._handle)
+ return BoolWithConfidence(result.value, confidence = result.confidence)
- def __int__(self):
- return self.value
+ @property
+ def volatile(self):
+ """Whether type is volatile (read/write)"""
+ result = core.BNIsTypeVolatile(self._handle)
+ return BoolWithConfidence(result.value, confidence = result.confidence)
+ @staticmethod
+ def from_bools(const:BoolWithConfidenceType, volatile:BoolWithConfidenceType) -> Tuple[BoolWithConfidence, BoolWithConfidence]:
+ _const = const
+ if const is None:
+ _const = BoolWithConfidence(False, confidence = 0)
+ elif isinstance(const, bool):
+ _const = BoolWithConfidence(const)
+ if not isinstance(_const, BoolWithConfidence):
+ raise ValueError(f"unhandled type {type(const)} for 'const' argument")
-@dataclass(frozen=True)
-class RegisterSet:
- regs:List['architecture.RegisterName']
- confidence:int=core.max_confidence
+ _volatile = volatile
+ if volatile is None:
+ _volatile = BoolWithConfidence(False, confidence = 0)
+ elif isinstance(volatile, bool):
+ _volatile = BoolWithConfidence(volatile)
+ if not isinstance(_volatile, BoolWithConfidence):
+ raise ValueError(f"unhandled type {type(volatile)} for 'volatile' argument")
- def __iter__(self) -> Generator['architecture.RegisterName', None, None]:
- for reg in self.regs:
- yield reg
+ return (_const, _volatile)
- def __getitem__(self, idx):
- return self.regs[idx]
+
+class PointerLike(CVQualifiedType):
+ @property
+ def target(self) -> Type:
+ """Target (read-only)"""
+ result = core.BNGetChildType(self._handle)
+ assert result is not None, "core.BNGetChildType returned None"
+ return Type.create(core.BNNewTypeReference(result.type), self._platform, result.confidence)
+
+@dataclass
+class Void(MutableType):
+ def immutable_copy(self, platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'VoidType':
+ return VoidType.create(platform, confidence)
def __len__(self):
- return len(self.regs)
+ return 0
- def with_confidence(self, confidence):
- return RegisterSet(list(self.regs), confidence=confidence)
+class VoidType(Type):
+ @classmethod
+ def create(cls, platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'VoidType':
+ core_void = core.BNCreateVoidType()
+ assert core_void is not None, "core.BNCreateVoidType returned None"
+ return cls(core.BNNewTypeReference(core_void), platform, confidence)
+ def create_mutable(self) -> 'Void':
+ return Void()
-class NamedTypeReference:
- def __init__(self, type_class = NamedTypeReferenceClass.UnknownNamedTypeClass, type_id = None, name = None, handle = None):
- if handle is None:
- if name is not None:
- name = QualifiedName(name)._get_core_struct()
- _handle = core.BNCreateNamedType(type_class, type_id, name)
- else:
- _handle = handle
- assert _handle is not None
- self.handle = _handle
- def __del__(self):
- core.BNFreeNamedTypeReference(self.handle)
+@dataclass
+class Integer(MutableType):
+ width:int
+ altname:str=""
+ signed:BoolWithConfidence=BoolWithConfidence(True)
- def __repr__(self):
- if self.type_class == NamedTypeReferenceClass.TypedefNamedTypeClass:
- return "<named type: typedef %s>" % str(self.name)
- if self.type_class == NamedTypeReferenceClass.StructNamedTypeClass:
- return "<named type: struct %s>" % str(self.name)
- if self.type_class == NamedTypeReferenceClass.UnionNamedTypeClass:
- return "<named type: union %s>" % str(self.name)
- if self.type_class == NamedTypeReferenceClass.EnumNamedTypeClass:
- return "<named type: enum %s>" % str(self.name)
- return "<named type: unknown %s>" % str(self.name)
+ def immutable_copy(self, **kwargs) -> 'IntegerType':
+ return IntegerType.create(self.width, self.signed, self.altname, **self.__dict__)
- def __eq__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents)
+ def __len__(self):
+ return self.width
- def __ne__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return not (self == other)
- def __hash__(self):
- return hash(ctypes.addressof(self.handle.contents))
+class IntegerType(CVQualifiedType):
+ @classmethod
+ def create(cls, width:int, sign:BoolWithConfidenceType=BoolWithConfidence(True), altname:str="", **kwargs) -> 'IntegerType':
+ if isinstance(sign, BoolWithConfidence):
+ _sign = sign.to_core_struct()
+ elif isinstance(sign, bool):
+ _sign = BoolWithConfidence(sign).to_core_struct()
- @property
- def type_class(self):
- return NamedTypeReferenceClass(core.BNGetTypeReferenceClass(self.handle))
+ builder_handle = core.BNCreateIntegerTypeBuilder(width, _sign, altname, **kwargs)
+ assert builder_handle is not None, "core.BNCreateIntegerTypeBuilder returned None"
+
+ handle = _TypeBuilder(builder_handle, **kwargs).finalize()
+ return cls(core.BNNewTypeReference(handle), **kwargs)
+
+ def create_mutable(self) -> 'Integer':
+ i = Integer(self.width, self.altname, self.signed)
+ i.__dict__['const']__ = self.const
+ i.__dict__['volatile']__ = self.volatile
+ return i
@property
- def type_id(self):
- return core.BNGetTypeReferenceId(self.handle)
+ def signed(self) -> BoolWithConfidence:
+ """Whether type is signed (read-only)"""
+ return BoolWithConfidence.from_core_struct(core.BNIsTypeSigned(self._handle))
+
+
+@dataclass
+class Bool(MutableType):
+ def immutable_copy(self, platform:'_platform.Platform'=None,
+ confidence:int=core.max_confidence) -> 'BoolType':
+ return BoolType.create(platform, confidence)
+
+ def __len__(self):
+ return 1
+
+
+class BoolType(Type):
+ @classmethod
+ def create(cls, platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'BoolType':
+ handle = core.BNCreateBoolType()
+ assert handle is not None, "core.BNCreateBoolType returned None"
+ return cls(core.BNNewTypeReference(handle), platform, confidence)
+
+ def create_mutable(self) -> 'Bool':
+ return Bool()
+
+@dataclass
+class Char(Integer):
+ width:int=1
+ altname:str=""
+ sign:bool=True
+
+ def as_char(self, platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'CharType':
+ return CharType.create(self.width, self.altname, self.sign, platform, confidence)
+
+
+class CharType(IntegerType):
+ @classmethod
+ def create(cls, width:int=1, altname:str="char", sign:bool=True,
+ platform:'_platform.Platform'=None, confidence:int=core.max_confidence, **kwargs) -> 'CharType':
+ return cls(IntegerType.create(width, sign, altname, **kwargs).handle, platform, confidence)
+
+ def create_mutable(self) -> 'Char':
+ return Char(self.width, self.altname, self.signed, self.const, self.volatile)
@property
- def name(self):
- name = core.BNGetTypeReferenceName(self.handle)
- result = QualifiedName._from_core_struct(name)
- core.BNFreeQualifiedName(name)
- return result
+ def signed(self) -> BoolWithConfidence:
+ return BoolWithConfidence(False, core.max_confidence)
- @staticmethod
- def generate_auto_type_ref(type_class, source, name):
- type_id = Type.generate_auto_type_id(source, name)
- return NamedTypeReference(type_class, type_id, name)
- @staticmethod
- def generate_auto_demangled_type_ref(type_class, name):
- type_id = Type.generate_auto_demangled_type_id(name)
- return NamedTypeReference(type_class, type_id, name)
+@dataclass
+class Float(MutableType):
+ width:int
+ altname:str=""
+ def immutable_copy(self, platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'FloatType':
+ return FloatType.create(self.width, self.altname, platform, confidence)
-@dataclass(frozen=True)
+ def __len__(self):
+ return self.width
+
+class FloatType(Type):
+ @classmethod
+ def create(cls, width:int, altname:str="", platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'FloatType':
+ """
+ ``float`` class method for creating floating point Types.
+
+ :param int width: width of the floating point number in bytes
+ :param str altname: alternate name for type
+ """
+ core_float = core.BNCreateFloatType(width, altname)
+ assert core_float is not None, "core.BNCreateFloatType returned None"
+ return cls(core.BNNewTypeReference(core_float), platform, confidence)
+
+ def create_mutable(self) -> 'Float':
+ return Float(self.width, self.altname)
+
+
+@dataclass
class StructureMember:
- type:'types.Type'
+ type:Union[Type, MutableType]
name:str
offset:int
+ def __post_init__(self):
+ self.type = self.type.mutable_copy()
+
def __repr__(self):
+ # TODO: Consider showing this differently if the type is mutable
if len(self.name) == 0:
- return f"<member: {self.type}, offset {self.offset:#x}>"
- return f"<{self.type.get_string_before_name()} {self.name}{self.type.get_string_after_name()}" + \
+ return f"<member: {self.type.immutable_copy()}, offset {self.offset:#x}>"
+ return f"<{self.type.immutable_copy().get_string_before_name()} {self.name}{self.type.immutable_copy().get_string_after_name()}" + \
f", offset {self.offset:#x}>"
+ # return f"<StructureMember: {self.type} {self.name}>"
-class Structure:
- def __init__(self, handle=None):
- if handle is None:
- _handle = core.BNCreateStructureBuilder()
- self._mutable = True
- else:
- _handle = handle
- self._mutable = isinstance(handle.contents, core.BNStructureBuilder)
- assert _handle is not None
- self._handle = _handle
+ def __len__(self):
+ return len(self.type)
+
+
+class StructureType(RegisteredNameType):
+ def __init__(self, handle, platform:'_platform.Platform'=None, confidence:int=core.max_confidence):
+ assert handle is not None, "Attempted to create EnumerationType with handle which is None"
+ super(StructureType, self).__init__(handle, platform, confidence)
+ struct_handle = core.BNGetTypeStructure(handle)
+ assert struct_handle is not None, "core.BNGetTypeStructure returned None"
+ self.struct_handle = struct_handle
+
+ @classmethod
+ def create(cls, members:MembersType=[], packed:bool=False, variant:StructureVariant=StructureVariant.StructStructureType,
+ platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'StructureType':
+ builder = core.BNCreateStructureBuilderWithOptions(variant, packed)
+ assert builder is not None, "core.BNCreateStructureBuilder returned None"
+
+ for member in members:
+ if isinstance(member, Tuple):
+ _type, _name = member
+ core.BNAddStructureBuilderMember(builder, _type.immutable_copy().to_core_struct(), _name)
+ elif isinstance(member, StructureMember):
+ core.BNAddStructureBuilderMemberAtOffset(builder, member.type.immutable_copy().to_core_struct(),
+ member.name, member.offset, False)
+ core_struct = core.BNFinalizeStructureBuilder(builder)
+ assert core_struct is not None, "core.BNFinalizeStructureBuilder returned None"
+ core_type = core.BNCreateStructureType(core_struct)
+ assert core_type is not None, "core.BNCreateStructureType returned None"
+ return cls(core.BNNewTypeReference(core_type), platform, confidence)
+
+ def create_mutable(self) -> 'Structure':
+ return Structure(self.members, self.alignment, self.width, self.type, self.packed)
+
+ @classmethod
+ def from_core_struct(cls, structure:core.BNStructure) -> 'StructureType':
+ return cls(core.BNNewTypeReference(core.BNCreateStructureType(structure)))
def __del__(self):
- if self._mutable:
- core.BNFreeStructureBuilder(self._handle)
- else:
- core.BNFreeStructure(self._handle)
+ if core is not None:
+ core.BNFreeStructure(self.struct_handle)
- def __repr__(self):
- return "<struct: size %#x>" % self.width
+ # TODO: Commented to pass unit tests
+ # def __repr__(self):
+ # return f"<struct: {self.registered_name}>"
def __eq__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
- return ctypes.addressof(self._handle.contents) == ctypes.addressof(other.handle.contents)
+ assert other.handle is not None
+ return ctypes.addressof(self.struct_handle.contents) == ctypes.addressof(other.handle.contents)
def __ne__(self, other):
if not isinstance(other, self.__class__):
@@ -1127,20 +1145,15 @@ class Structure:
return not (self == other)
def __hash__(self):
- return hash(ctypes.addressof(self._handle.contents))
+ return hash(ctypes.addressof(self.struct_handle.contents))
def __getitem__(self, name:str) -> StructureMember:
member = None
try:
- if self._mutable:
- member = core.BNGetStructureBuilderMemberByName(self._handle, name)
- if member is None:
- raise ValueError(f"Member {name} is not part of structure")
- else:
- member = core.BNGetStructureMemberByName(self._handle, name)
- if member is None:
- raise ValueError(f"Member {name} is not part of structure")
- return StructureMember(Type(core.BNNewTypeReference(member.contents.type), confidence=member.contents.typeConfidence),
+ member = core.BNGetStructureMemberByName(self.struct_handle, name)
+ if member is None:
+ raise ValueError(f"Member {name} is not part of structure")
+ return StructureMember(Type.create(core.BNNewTypeReference(member.contents.type), confidence=member.contents.typeConfidence),
member.contents.name, member.contents.offset)
finally:
if member is not None:
@@ -1149,44 +1162,24 @@ class Structure:
def member_at_offset(self, offset:int) -> StructureMember:
member = None
try:
- if self._mutable:
- member = core.BNGetStructureBuilderMemberAtOffset(self._handle, offset, None)
- if member is None:
- raise ValueError(f"No member exists a offset {offset}")
- else:
- member = core.BNGetStructureMemberAtOffset(self._handle, offset, None)
- if member is None:
- raise ValueError(f"No member exists a offset {offset}")
- return StructureMember(Type(core.BNNewTypeReference(member.contents.type), confidence=member.contents.typeConfidence),
+ member = core.BNGetStructureMemberAtOffset(self.struct_handle, offset, None)
+ if member is None:
+ raise ValueError(f"No member exists a offset {offset}")
+ return StructureMember(Type.create(core.BNNewTypeReference(member.contents.type), confidence=member.contents.typeConfidence),
member.contents.name, member.contents.offset)
finally:
core.BNFreeStructureMember(member)
@property
- def handle(self):
- if self._mutable:
- # First use of a mutable Structure makes it immutable
- finalized = core.BNFinalizeStructureBuilder(self._handle)
- assert finalized is not None, "core.BNFinalizeStructureBuilder returned None"
- core.BNFreeStructureBuilder(self._handle)
- self._handle = finalized
- self._mutable = False
- return self._handle
-
- @property
def members(self):
"""Structure member list (read-only)"""
count = ctypes.c_ulonglong()
- if self._mutable:
- members = core.BNGetStructureBuilderMembers(self._handle, count)
- assert members is not None, "core.BNGetStructureBuilderMembers returned None"
- else:
- members = core.BNGetStructureMembers(self._handle, count)
- assert members is not None, "core.BNGetStructureMembers returned None"
+ members = core.BNGetStructureMembers(self.struct_handle, count)
+ assert members is not None, "core.BNGetStructureMembers returned None"
try:
result = []
for i in range(0, count.value):
- result.append(StructureMember(Type(core.BNNewTypeReference(members[i].type), confidence=members[i].typeConfidence),
+ result.append(StructureMember(Type.create(core.BNNewTypeReference(members[i].type), confidence=members[i].typeConfidence),
members[i].name, members[i].offset))
finally:
core.BNFreeStructureMemberList(members, count.value)
@@ -1195,137 +1188,264 @@ class Structure:
@property
def width(self):
"""Structure width"""
- if self._mutable:
- return core.BNGetStructureBuilderWidth(self._handle)
- return core.BNGetStructureWidth(self._handle)
-
- @width.setter
- def width(self, new_width):
- if not self._mutable:
- raise AttributeError("Finalized Structure object is immutable, use mutable_copy()")
- core.BNSetStructureBuilderWidth(self._handle, new_width)
+ return core.BNGetStructureWidth(self.struct_handle)
@property
def alignment(self):
"""Structure alignment"""
- if self._mutable:
- return core.BNGetStructureBuilderAlignment(self._handle)
- return core.BNGetStructureAlignment(self._handle)
-
- @alignment.setter
- def alignment(self, align):
- if not self._mutable:
- raise AttributeError("Finalized Structure object is immutable, use mutable_copy()")
- core.BNSetStructureBuilderAlignment(self._handle, align)
+ return core.BNGetStructureAlignment(self.struct_handle)
@property
def packed(self):
- if self._mutable:
- return core.BNIsStructureBuilderPacked(self._handle)
- return core.BNIsStructurePacked(self._handle)
+ return core.BNIsStructurePacked(self.struct_handle)
+
+ @property
+ def type(self) -> StructureVariant:
+ return StructureVariant(core.BNGetStructureType(self.struct_handle))
+
+ def with_replaced_structure(self, from_struct, to_struct) -> 'StructureType':
+ return Type.create(core.BNStructureWithReplacedStructure(self.struct_handle, from_struct.handle, to_struct.handle))
+
+ def with_replaced_enumeration(self, from_enum, to_enum) -> 'StructureType':
+ return Type.create(core.BNStructureWithReplacedEnumeration(self.struct_handle, from_enum.handle, to_enum.handle))
+
+ def with_replaced_named_type_reference(self, from_ref, to_ref) -> 'StructureType':
+ return Type.create(core.BNStructureWithReplacedNamedTypeReference(self.struct_handle, from_ref.handle, to_ref.handle))
+
+ def generate_named_type_reference(self, guid:str, name:QualifiedName):
+ if self.type == StructureVariant.StructStructureType:
+ ntr_type = NamedTypeReferenceClass.StructNamedTypeClass
+ elif self.type == StructureVariant.UnionStructureType:
+ ntr_type = NamedTypeReferenceClass.UnionNamedTypeClass
+ else:
+ ntr_type = NamedTypeReferenceClass.ClassNamedTypeClass
+ return NamedTypeReferenceType.create(ntr_type, guid, name, self.alignment,
+ self.width, self.platform, self.confidence)
+
+
+@dataclass
+class Structure(MutableType):
+ members:List[StructureMember] = field(default_factory=list)
+ _alignment:int=1
+ _width:int=0
+ type:StructureVariant=StructureVariant.StructStructureType
+ _packed:bool=False
+
+ def immutable_copy(self, platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'StructureType':
+ return StructureType.create(self.members, self.packed, self.type, platform, confidence)
+
+ @property
+ def packed(self) -> bool:
+ return self._packed
@packed.setter
- def packed(self, value):
- if not self._mutable:
- raise AttributeError("Finalized Structure object is immutable, use mutable_copy()")
- core.BNSetStructureBuilderPacked(self._handle, value)
+ def packed(self, value:bool) -> None:
+ self._packed = value
@property
- def union(self):
- if self._mutable:
- return core.BNIsStructureBuilderUnion(self._handle)
- return core.BNIsStructureUnion(self._handle)
+ def alignment(self) -> int:
+ return self._alignment
+
+ @alignment.setter
+ def alignment(self, value:int) -> None:
+ if value == 1:
+ return
+ if value < 1:
+ raise ValueError("Can't set alignment to < 1")
+ self._alignment = value
@property
- def type(self):
- if self._mutable:
- return StructureType(core.BNGetStructureBuilderType(self._handle))
- return StructureType(core.BNGetStructureType(self._handle))
+ def width(self) -> int:
+ return self._width
- @type.setter
- def type(self, value):
- if not self._mutable:
- raise AttributeError("Finalized Structure object is immutable, use mutable_copy()")
- core.BNSetStructureBuilderType(self._handle, value)
+ @width.setter
+ def width(self, value:int) -> None:
+ # if greater than the current width:
+ # expands the structure's size
+ # if less than the current width:
+ # shrinks the structure's size removing any members which would exist outside the structure's bounds
+ if value < 0:
+ raise ValueError("Width of structure can not be negative")
- def append(self, t, name = ""):
- if not self._mutable:
- raise AttributeError("Finalized Structure object is immutable, use mutable_copy()")
- tc = core.BNTypeWithConfidence()
- tc.type = t.handle
- tc.confidence = t.confidence
- core.BNAddStructureBuilderMember(self._handle, tc, name)
+ if value < self._width:
+ amount = self._width - (self._width - value)
+ self.clear_members(value, amount)
+ self._width = value
- def insert(self, offset, t, name = "", overwriteExisting = True):
- if not self._mutable:
- raise AttributeError("Finalized Structure object is immutable, use mutable_copy()")
- tc = core.BNTypeWithConfidence()
- tc.type = t.handle
- tc.confidence = t.confidence
- core.BNAddStructureBuilderMemberAtOffset(self._handle, tc, name, offset, overwriteExisting)
+ def __repr__(self):
+ return f"<struct: size {self.width:#x}>"
- def remove(self, i):
- if not self._mutable:
- raise AttributeError("Finalized Structure object is immutable, use mutable_copy()")
- core.BNRemoveStructureBuilderMember(self._handle, i)
+ def __getitem__(self, name:str) -> Optional[StructureMember]:
+ for member in self.members:
+ if member.name == name:
+ return member
+ return None
- def replace(self, i, t, name = "", overwriteExisting = True):
- if not self._mutable:
- raise AttributeError("Finalized Structure object is immutable, use mutable_copy()")
- tc = core.BNTypeWithConfidence()
- tc.type = t.handle
- tc.confidence = t.confidence
- core.BNReplaceStructureBuilderMember(self._handle, i, tc, name, overwriteExisting)
+ def __iter__(self) -> Generator[StructureMember, None, None]:
+ for member in self.members:
+ yield member
- def mutable_copy(self):
- if self._mutable:
- return Structure(core.BNDuplicateStructureBuilder(self._handle))
- return Structure(core.BNCreateStructureBuilderFromStructure(self._handle))
+ def __len__(self) -> int:
+ return self._width
- def with_replaced_structure(self, from_struct, to_struct):
- return Structure(core.BNStructureWithReplacedStructure(self._handle, from_struct.handle, to_struct.handle))
+ def member_at_offset(self, offset:int) -> Optional[StructureMember]:
+ for member in self.members:
+ if member.offset == offset:
+ return member
+ return None
- def with_replaced_enumeration(self, from_enum, to_enum):
- return Structure(core.BNStructureWithReplacedEnumeration(self._handle, from_enum.handle, to_enum.handle))
+ def index_by_name(self, name:MemberName) -> Optional[MemberIndex]:
+ for i, member in enumerate(self.members):
+ if member.name == name:
+ return i
+ return None
- def with_replaced_named_type_reference(self, from_ref, to_ref):
- return Structure(core.BNStructureWithReplacedNamedTypeReference(self._handle, from_ref.handle, to_ref.handle))
+ def index_by_offset(self, offset:MemberOffset) -> Optional[MemberIndex]:
+ for i, member in enumerate(self.members):
+ if member.offset == offset:
+ return i
+ return None
+ def index_from(self, index:Optional[MemberIndex]=None, name:Optional[MemberName]=None, offset:Optional[MemberOffset]=None) -> MemberIndex:
+ if index is not None:
+ if index >= len(self.members):
+ raise IndexError("list index out of range")
+ elif name is not None:
+ index = self.index_by_name(name)
+ if index is None:
+ raise ValueError(f"StructureMember {name} doesn't exist")
+ elif offset is not None:
+ index = self.index_by_offset(offset)
+ if index is None:
+ raise ValueError(f"No StructureMember at offset exists")
+ else:
+ raise ValueError("One of the following must")
-@dataclass(frozen=True)
-class EnumerationMember:
- name:str
- value:int
- default:bool
+ return index
- def __repr__(self):
- return f"<{self.name} = {self.value:#x}>"
+ def erase(self, index:MemberIndex=None, name:MemberName=None, offset:MemberOffset=None) -> None:
+ # removes the specified item shrinking the total size of the structure and adjusting
+ # the offset of any members with offsets greater than the offset of member[index].
+ # In the case where there are multiple members which overlap the erased item they will be erased too
+ # but the structure will only be shrunken by the specified member's width
+ # raise exception if the index doesn't exist
+ # raises exception if more not exactly one of index/name/offset are not None
+ item = self.members[self.index_from(index, name, offset)]
+ self.clear_members(item.offset, len(item))
+ self.adjust_space(item.offset, -len(item))
+ def clear(self, index:MemberIndex=None, name:MemberName=None, offset:MemberOffset=None) -> None:
+ # clears the member at the index/member-name. No adjustment is made to other members or the structure's size
+ # raise exception if the index doesn't exist
+ del self.members[self.index_from(index, name, offset)]
-class Enumeration:
- def __init__(self, handle=None):
- if handle is None:
- _handle = core.BNCreateEnumerationBuilder()
- self._mutable = True
- else:
- _handle = handle
- self._mutable = isinstance(handle.contents, core.BNEnumerationBuilder)
- assert _handle is not None
- self._handle = _handle
+ def clear_members(self, offset:MemberOffset, size:int) -> None:
+ # clears members which overlap offset
+ to_clear = []
+ for i, member in enumerate(self.members):
+ if member.offset >= offset and member.offset < offset + size:
+ to_clear.append(i)
+ elif member.offset < offset and member.offset + len(member) > offset:
+ to_clear.append(i)
+ for i in to_clear:
+ self.clear(index=i)
+
+ def replace_member(self, new_name:MemberName, type:SomeType, index:MemberIndex=None, old_name:MemberName=None, offset:MemberOffset=None) -> None:
+ # replaces any members within the structure which overlap member[index]
+ index = self.index_from(index, old_name, offset)
+ item = self.members[index]
+ self.clear_members(item.offset, len(item))
+ self.members.insert(index, StructureMember(type, new_name, item.offset))
+
+ def append(self, name:MemberName, type:SomeType) -> 'Structure':
+ # appends a structure at the end of the structure growing the structure
+ self.members.append(StructureMember(type.mutable_copy(), name, self._width))
+ self._width += len(type)
+ return self
+
+ def add_member_at_offset(self, name:MemberName, type:SomeType, offset:MemberOffset) -> 'Structure':
+ # Adds structure member to the given offset first clearing any members within the range offset-offset+len(type)
+ self.clear_members(offset, len(type))
+ self.members.append(StructureMember(type, name, offset))
+ self.members = sorted(self.members, key=lambda m: m.offset)
+ return self
+
+ def adjust_space(self, offset:int, size:int) -> None:
+ # adds or removes undefined space at the given offset and size
+ # removes space and clears overlapping members if size is negative
+ self.members = sorted(self.members, key=lambda m: m.offset)
+
+ if size < -self._width:
+ size = -self._width
+
+ if size < 0:
+ self.clear_members(offset, size)
+
+ alignment = 0
+ if size % self._alignment != 0:
+ alignment = self._alignment - (abs(size) % self._alignment)
+
+ new_members = []
+ for member in self.members:
+ if member.offset > offset:
+ new_offset = member.offset + size + alignment
+ new_members.append(StructureMember(member.type, member.name, new_offset))
+ self.members = new_members
+ self._width += size
+
+
+class EnumerationType(RegisteredNameType, IntegerType):
+ def __init__(self, handle, platform:'_platform.Platform'=None, confidence:int=core.max_confidence):
+ assert handle is not None, "Attempted to create EnumerationType without handle"
+ super(EnumerationType, self).__init__(handle, platform, confidence)
+ enum_handle = core.BNGetTypeEnumeration(handle)
+ assert enum_handle is not None, "core.BNGetTypeEnumeration returned None"
+ self.enum_handle = enum_handle
+
+ @classmethod
+ def create(cls, arch:Optional['architecture.Architecture'], members:EnumMembersType=[], width:Optional[int]=None,
+ sign:BoolWithConfidenceType=BoolWithConfidence(False), platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'EnumerationType':
+ if width is None:
+ if arch is None:
+ raise ValueError("One of the following parameters must not be None: (arch, width)")
+ width = arch.default_int_size
+ if width == 0:
+ raise ValueError("enumeration width must not be 0")
+
+ builder = core.BNCreateEnumerationBuilder()
+ assert builder is not None, "core.BNCreateEnumerationType returned None"
+ for i, member in enumerate(members):
+ value = i
+ name = member
+ if isinstance(member, Tuple):
+ value, name = member
+ elif isinstance(member, EnumerationMember):
+ value = member.value
+ name = member.name
+ if value is None:
+ core.BNAddEnumerationBuilderMember(builder, name)
+ else:
+ core.BNAddEnumerationBuilderMemberWithValue(builder, name, value)
+ core_enum = core.BNFinalizeEnumerationBuilder(builder)
+ assert core_enum is not None, "core.BNFinalizeEnumerationBuilder returned None"
+ core_type = core.BNCreateEnumerationTypeOfWidth(core_enum, width, sign)
+ assert core_type is not None, "core.BNCreateEnumerationTypeOfWidth returned None"
+ return cls(core.BNNewTypeReference(core_type), platform, confidence)
+
+ def create_mutable(self) -> 'Enumeration':
+ return Enumeration(self.members, len(self), self.signed)
def __del__(self):
- if self._mutable:
- core.BNFreeEnumerationBuilder(self._handle)
- else:
- core.BNFreeEnumeration(self._handle)
+ if core is not None:
+ core.BNFreeEnumeration(self.enum_handle)
- def __repr__(self):
- return "<enum: %s>" % repr(self.members)
+ # def __repr__(self):
+ # return "<enum: %s>" % repr(self.members)
def __eq__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
- return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents)
+ return ctypes.addressof(self.enum_handle.contents) == ctypes.addressof(other.enum_handle.contents)
def __ne__(self, other):
if not isinstance(other, self.__class__):
@@ -1333,57 +1453,587 @@ class Enumeration:
return not (self == other)
def __hash__(self):
- return hash(ctypes.addressof(self.handle.contents))
-
- @property
- def handle(self):
- if self._mutable:
- # First use of a mutable Enumeration makes it immutable
- finalized = core.BNFinalizeEnumerationBuilder(self._handle)
- assert finalized is not None
- core.BNFreeEnumerationBuilder(self._handle)
- self._handle = finalized
- self._mutable = False
- return self._handle
+ return hash(ctypes.addressof(self.enum_handle.contents))
@property
def members(self):
"""Enumeration member list (read-only)"""
count = ctypes.c_ulonglong()
- if self._mutable:
- members = core.BNGetEnumerationBuilderMembers(self._handle, count)
- assert members is not None, "core.BNGetEnumerationBuilderMembers returned None"
- else:
- members = core.BNGetEnumerationMembers(self._handle, count)
- assert members is not None, "core.BNGetEnumerationMembers returned None"
+ members = core.BNGetEnumerationMembers(self.enum_handle, count)
+ assert members is not None, "core.BNGetEnumerationMembers returned None"
result = []
for i in range(0, count.value):
- result.append(EnumerationMember(members[i].name, members[i].value, members[i].isDefault))
+ result.append(EnumerationMember(members[i].name, members[i].value))
core.BNFreeEnumerationMemberList(members, count.value)
return result
- def append(self, name, value = None):
- if not self._mutable:
- raise AttributeError("Finalized Enumeration object is immutable, use mutable_copy()")
- if value is None:
- core.BNAddEnumerationBuilderMember(self._handle, name)
- else:
- core.BNAddEnumerationBuilderMemberWithValue(self._handle, name, value)
+ def generate_named_type_reference(self, guid:str, name:QualifiedName):
+ ntr_type = NamedTypeReferenceClass.EnumNamedTypeClass
+ return NamedTypeReferenceType.create(ntr_type, guid, name,
+ platform=self.platform, confidence=self.confidence)
+
+@dataclass(frozen=True)
+class EnumerationMember:
+ name:str
+ value:Optional[int]
+
+ def __repr__(self):
+ value = f"{self.value:#x}" if self.value is not None else "auto()"
+ return f"<{self.name} = {value}>"
+
+
+@dataclass
+class Enumeration(MutableType):
+ members:List[EnumerationMember] = field(default_factory=list)
+ width:int=4
+ sign:BoolWithConfidence=BoolWithConfidence(False)
+
+ def __repr__(self):
+ return "<enum: %s>" % repr(self.members)
+
+ def __len__(self):
+ return self.width
+
+ def immutable_copy(self, platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'EnumerationType':
+ return EnumerationType.create(None, self.members, self.width, self.sign, platform, confidence)
+
+ def append(self, name, value = None) -> 'Enumeration':
+ self.members.append(EnumerationMember(name, value))
+ return self
def remove(self, i):
- if not self._mutable:
- raise AttributeError("Finalized Enumeration object is immutable, use mutable_copy()")
- core.BNRemoveEnumerationBuilderMember(self._handle, i)
+ del self.members[i]
def replace(self, i, name, value):
- if not self._mutable:
- raise AttributeError("Finalized Enumeration object is immutable, use mutable_copy()")
- core.BNReplaceEnumerationBuilderMember(self._handle, i, name, value)
+ self.remove(i)
+ self.members.insert(i, EnumerationMember(name, value))
+
+ def __iter__(self) -> Generator[EnumerationMember, None, None]:
+ for i, member in enumerate(self.members):
+ if member.value is None:
+ yield EnumerationMember(member.name, i)
+ else:
+ yield member
+
+ def __getitem__(self, value:Union[str, int, slice]):
+ if isinstance(value, str) and value in self.__dict__:
+ return self.__dict__[value]
+
+ if isinstance(value, str):
+ for member in self.members:
+ if member.name == value:
+ return member
+ return None
+ elif isinstance(value, int):
+ return self.members[value]
+ elif isinstance(value, slice): # not combined with the previous check due to pyright bug
+ return self.members[value]
+ else:
+ raise ValueError(f"Incompatible type {type(value)} for __getitem__")
+
+ def __setitem__(self, item, value):
+ if isinstance(item, str):
+ for i, member in enumerate(self.members):
+ if member.name == item:
+ self.members[i] = EnumerationMember(member.name, value)
+ elif isinstance(item, int) and isinstance(value, EnumerationMember):
+ self.members[item] = value
+ raise ValueError(f"Incompatible type: {type(item)} for __setitem__")
+
+
+@dataclass
+class Pointer(MutableType):
+ _target:Optional[SomeType] = None
+ width:Optional[int] = None
+ arch:Optional['architecture.Architecture'] = None
+ const:BoolWithConfidenceType=BoolWithConfidence(False)
+ volatile:BoolWithConfidenceType=BoolWithConfidence(False)
+ ref_type:ReferenceType=ReferenceType.PointerReferenceType
+
+ def __post_init__(self):
+ if self._target is not None:
+ self._target = self._target.mutable_copy()
+ assert self.arch is not None or self.width is not None, f"Must specify either an architecture or a width {self.arch} : {self.width}"
+ if self.arch is not None:
+ self.width = self.arch.address_size
+
+ def immutable_copy(self, platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'PointerType':
+ assert self._target is not None and self.width is not None, f"Target not set for Pointer(MutableType) {self._target}, {self.width}"
+ return PointerType.create_with_width(self.width, self._target, self.const, self.volatile,
+ self.ref_type, platform, confidence)
+
+ @property
+ def target(self) -> MutableType:
+ assert isinstance(self._target, MutableType)
+ return self._target
+
+ @target.setter
+ def target(self, value:SomeType): # type: ignore
+ self._target = value.mutable_copy()
+
+ def __len__(self):
+ return self.width
+
+class PointerType(PointerLike):
+ @property
+ def ref_type(self) -> ReferenceType:
+ return core.BNTypeGetReferenceType(self._handle)
+
+ @classmethod
+ def create(cls, arch:'architecture.Architecture', type:SomeType, const:BoolWithConfidenceType=False,
+ volatile:BoolWithConfidenceType=False, ref_type:ReferenceType=ReferenceType.PointerReferenceType,
+ platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'PointerType':
+ return cls.create_with_width(arch.address_size, type, const, volatile, ref_type, platform, confidence)
+
+ @classmethod
+ def create_with_width(cls, width:int, type:SomeType, const:BoolWithConfidenceType=False,
+ volatile:BoolWithConfidenceType=False, ref_type:ReferenceType=None, platform:'_platform.Platform'=None,
+ confidence:int=core.max_confidence) -> 'PointerType':
+ _const, _volatile = CVQualifiedType.from_bools(const, volatile)
+ type = type.immutable_copy()
+ if ref_type is None:
+ ref_type = ReferenceType.PointerReferenceType
+
+ type_conf = type.to_core_struct()
+ core_type = core.BNCreatePointerTypeOfWidth(width, type_conf, _const.to_core_struct(),
+ _volatile.to_core_struct(), ref_type)
+ assert core_type is not None, "core.BNCreatePointerTypeOfWidth returned None"
+ return Type.create(core.BNNewTypeReference(core_type), platform, confidence)
+
+ def create_mutable(self) -> 'Pointer':
+ return Pointer(self.target, self.width, None, self.const, self.volatile, self.ref_type)
+
+
+@dataclass
+class Array(MutableType):
+ count:int
+ element_type:MutableType
+
+ def __post_init__(self):
+ self.element_type = self.element_type.mutable_copy()
+
+ def immutable_copy(self, platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'ArrayType':
+ return ArrayType.create(self.element_type.immutable_copy(), self.count, platform, confidence)
+
+ def __len__(self):
+ return self.count * len(self.element_type)
+
+
+class ArrayType(Type):
+ @classmethod
+ def create(cls, element_type:Type, count:int, platform:'_platform.Platform'=None, confidence:int=core.max_confidence):
+ type_conf = element_type.to_core_struct()
+ core_array = core.BNCreateArrayType(type_conf, count)
+ assert core_array is not None, "core.BNCreateArrayType returned None"
+ return cls(core.BNNewTypeReference(core_array))
+
+ def create_mutable(self) -> 'Array':
+ return Array(self.count, self.element_type.mutable_copy())
+
+ @property
+ def count(self):
+ """Type count (read-only)"""
+ return core.BNGetTypeElementCount(self._handle)
+
+ @property
+ def element_type(self) -> Type:
+ result = core.BNGetChildType(self._handle)
+ assert result is not None, "core.BNGetChildType returned None"
+ return Type.create(core.BNNewTypeReference(result.type), self._platform, result.confidence)
+
+
+@dataclass
+class Function(MutableType):
+ _return_type:Optional[SomeType] = None
+ parameters:List[FunctionParameter] = field(default_factory=list)
+ calling_convention:Optional['callingconvention.CallingConvention'] = None
+ variable_arguments:BoolWithConfidenceType = BoolWithConfidence(False)
+ stack_adjustment:OffsetWithConfidence = OffsetWithConfidence(0)
+
+ def __post_init__(self):
+ if self._return_type is not None:
+ self._return_type = self._return_type.mutable_copy()
+ if len(self.parameters) > 0:
+ self.parameters = [param.mutable_copy() for param in self.parameters]
+
+ def immutable_copy(self, platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'FunctionType':
+ immutable_parameters = [param.immutable_copy() for param in self.parameters]
+ if self._return_type is None:
+ self._return_type = Type.void()
+ return FunctionType.create(self._return_type.immutable_copy(), immutable_parameters, self.calling_convention,
+ self.variable_arguments, self.stack_adjustment, platform, confidence)
+
+ @property
+ def return_type(self):
+ return self._return_type
+
+ @return_type.setter
+ def return_type(self, value:SomeType):
+ self._return_type = value.mutable_copy()
+
+ def append(self, type:Union[SomeType, FunctionParameter], name:str=""):
+ if isinstance(type, FunctionParameter):
+ self.parameters.append(type.mutable_copy())
+ else:
+ self.parameters.append(FunctionParameter(type.mutable_copy(), name))
+
+ def __len__(self):
+ return 0
+
+class FunctionType(Type):
+ @classmethod
+ def create(cls, ret:Optional[Type]=None, params:ParamsType=[],
+ calling_convention:'callingconvention.CallingConvention'=None, variable_arguments:BoolWithConfidenceType=BoolWithConfidence(False),
+ stack_adjust:OffsetWithConfidence=OffsetWithConfidence(0), platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'FunctionType':
+ if ret is None:
+ ret = VoidType.create()
+ param_buf = (core.BNFunctionParameter * len(params))()
+ for i in range(0, len(params)):
+ param = params[i]
+ core_param = param_buf[i]
+ if isinstance(param, Type):
+ core_param.name = ""
+ core_param.type = param.handle
+ core_param.typeConfidence = param.confidence
+ core_param.defaultLocation = True
+ elif isinstance(param, FunctionParameter):
+ core_param.name = param.name
+ core_param.type = param.type.immutable_copy().handle
+ core_param.typeConfidence = param.type.immutable_copy().confidence
+ if param.location is None:
+ core_param.defaultLocation = True
+ else:
+ core_param.defaultLocation = False
+ core_param.location.type = param.location.source_type
+ core_param.location.index = param.location.index
+ core_param.location.storage = param.location.storage
+ elif isinstance(param, tuple):
+ t, name = param
+ core_param.name = name
+ core_param.type = t.handle
+ core_param.typeConfidence = t.confidence
+ core_param.defaultLocation = True
+
+ ret_conf = ret.to_core_struct()
+
+ conv_conf = core.BNCallingConventionWithConfidence()
+ if calling_convention is None:
+ conv_conf.convention = None
+ conv_conf.confidence = 0
+ else:
+ conv_conf.convention = calling_convention.handle
+ conv_conf.confidence = calling_convention.confidence
+
+ if isinstance(variable_arguments, bool):
+ _variable_arguments = BoolWithConfidence(variable_arguments)
+ elif isinstance(variable_arguments, BoolWithConfidence):
+ _variable_arguments = variable_arguments
+ elif variable_arguments is None:
+ _variable_arguments = BoolWithConfidence(False)
+ else:
+ raise ValueError(f"variable_arguments parameter of unhandled type: {type(variable_arguments)}")
+
+ if isinstance(stack_adjust, int):
+ _stack_adjust = OffsetWithConfidence(stack_adjust)
+ elif isinstance(stack_adjust, OffsetWithConfidence):
+ _stack_adjust = stack_adjust
+ elif stack_adjust is None:
+ _stack_adjust = OffsetWithConfidence(0)
+ else:
+ raise ValueError(f"stack_adjust parameter of unhandled type: {type(variable_arguments)}")
+
+ func_type = core.BNCreateFunctionType(ret_conf, conv_conf, param_buf, len(params),
+ _variable_arguments.to_core_struct(), _stack_adjust.to_core_struct())
+ return cls(core.BNNewTypeReference(func_type), platform, confidence)
+
+ def create_mutable(self) -> 'Function':
+ return Function(self.return_value.mutable_copy(), self.parameters, self.calling_convention, self.has_variable_arguments, self.stack_adjustment)
+
+ @property
+ def stack_adjustment(self) -> OffsetWithConfidence:
+ """Stack adjustment for function (read-only)"""
+ result = core.BNGetTypeStackAdjustment(self._handle)
+ return OffsetWithConfidence(result.value, confidence = result.confidence)
+
+ @property
+ def return_value(self) -> Type:
+ """Return value (read-only)"""
+ result = core.BNGetChildType(self._handle)
+ if result is None:
+ return Type.void()
+ return Type.create(core.BNNewTypeReference(result.type), platform = self._platform, confidence = result.confidence)
+
+ @property
+ def calling_convention(self) -> Optional[callingconvention.CallingConvention]:
+ """Calling convention (read-only)"""
+ result = core.BNGetTypeCallingConvention(self._handle)
+ if not result.convention:
+ return None
+ return callingconvention.CallingConvention(None, handle = result.convention, confidence = result.confidence)
+
+ @property
+ def parameters(self) -> List[FunctionParameter]:
+ """Type parameters list (read-only)"""
+ count = ctypes.c_ulonglong()
+ params = core.BNGetTypeParameters(self._handle, count)
+ assert params is not None, "core.BNGetTypeParameters returned None"
+ result = []
+ for i in range(0, count.value):
+ param_type = Type.create(core.BNNewTypeReference(params[i].type), platform = self._platform, confidence = params[i].typeConfidence)
+ if params[i].defaultLocation:
+ param_location = None
+ else:
+ name = params[i].name
+ if (params[i].location.type == VariableSourceType.RegisterVariableSourceType) and (self._platform is not None):
+ name = self._platform.arch.get_reg_name(params[i].location.storage)
+ elif params[i].location.type == VariableSourceType.StackVariableSourceType:
+ name = "arg_%x" % params[i].location.storage
+ param_location = variable.VariableNameAndType(params[i].location.type, params[i].location.index,
+ params[i].location.storage, name, param_type)
+ result.append(FunctionParameter(param_type, params[i].name, param_location))
+ core.BNFreeTypeParameterList(params, count.value)
+ return result
+
+ @property
+ def has_variable_arguments(self) -> BoolWithConfidence:
+ """Whether type has variable arguments (read-only)"""
+ result = core.BNTypeHasVariableArguments(self._handle)
+ return BoolWithConfidence(result.value, confidence = result.confidence)
+
+ @property
+ def can_return(self) -> BoolWithConfidence:
+ """Whether type can return"""
+ result = core.BNFunctionTypeCanReturn(self._handle)
+ return BoolWithConfidence(result.value, confidence = result.confidence)
+
+
+# @dataclass
+# class Value(MutableType):
+# pass
+
+
+# class ValueType(Type):
+# pass
+
+
+@dataclass
+class NamedTypeReference(MutableType):
+ name:QualifiedName
+ id:str
+ named_type_class:NamedTypeReferenceClass=NamedTypeReferenceClass.UnknownNamedTypeClass
+ alignment:int = 0
+ width:int = 0
+
+ def __repr__(self):
+ if self.named_type_class == NamedTypeReferenceClass.TypedefNamedTypeClass:
+ return "<named type: typedef %s>" % str(self.name)
+ if self.named_type_class == NamedTypeReferenceClass.StructNamedTypeClass:
+ return "<named type: struct %s>" % str(self.name)
+ if self.named_type_class == NamedTypeReferenceClass.UnionNamedTypeClass:
+ return "<named type: union %s>" % str(self.name)
+ if self.named_type_class == NamedTypeReferenceClass.EnumNamedTypeClass:
+ return "<named type: enum %s>" % str(self.name)
+ return "<named type: unknown >"
+
+ def immutable_copy(self, platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'NamedTypeReferenceType':
+ return NamedTypeReferenceType.create(self.named_type_class, self.id, self.name, self.alignment, self.width,
+ platform, confidence)
+
+ def __len__(self):
+ return self.width
+
+class NamedTypeReferenceType(RegisteredNameType):
+ def __init__(self, handle, platform:'_platform.Platform'=None, confidence:int=core.max_confidence, ntr_handle=None):
+ assert handle is not None, "Attempting to create NamedTypeReferenceType handle which is None"
+ super(NamedTypeReferenceType, self).__init__(handle, platform, confidence)
+ if ntr_handle is None:
+ ntr_handle = core.BNGetTypeNamedTypeReference(handle)
+ assert ntr_handle is not None, "core.BNGetTypeNamedTypeReference returned None"
+ self.ntr_handle = ntr_handle
+
+ @classmethod
+ def create(cls, named_type_class:NamedTypeReferenceClass, guid:Optional[str],
+ name:QualifiedName, alignment:int=0, width:int=0, platform:'_platform.Platform'=None,
+ confidence:int=core.max_confidence) -> 'NamedTypeReferenceType':
+ _guid = guid
+ if guid is None:
+ _guid = str(uuid.uuid4())
+
+ _name = QualifiedName(name)._get_core_struct()
+ core_ntr = core.BNCreateNamedType(named_type_class, _guid, _name)
+ assert core_ntr is not None, "core.BNCreateNamedType returned None"
+ core_type = core.BNCreateNamedTypeReference(core_ntr, width, alignment)
+ assert core_type is not None, "core.BNCreateNamedTypeReference returned None"
+ return cls(core.BNNewTypeReference(core_type), platform, confidence)
+
+ @classmethod
+ def create_from_type(cls, name:QualifiedName, type:Optional[Type], guid:Optional[str]=None,
+ platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'NamedTypeReferenceType':
+ _guid = guid
+ if _guid is None:
+ _guid = str(uuid.uuid4())
+
+ if type is None:
+ return cls.create(NamedTypeReferenceClass.UnknownNamedTypeClass, _guid, name)
+ else:
+ return type.generate_named_type_reference(_guid, name)
+
+ @classmethod
+ def create_from_registered_type(cls, view:'binaryview.BinaryView', name:QualifiedName,
+ platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'NamedTypeReferenceType':
+ _name = QualifiedName(name)._get_core_struct()
+ core_type = core.BNCreateNamedTypeReferenceFromType(view.handle, _name)
+ assert core_type is not None, "core.BNCreateNamedTypeReferenceFromType returned None"
+ return cls(core.BNNewTypeReference(core_type), platform, confidence)
+
+ def create_mutable(self) -> 'NamedTypeReference':
+ return NamedTypeReference(self.name, self.type_id, self.named_type_class, self.alignment, self.width)
+
+ def __del__(self):
+ if core is not None:
+ core.BNFreeNamedTypeReference(self.ntr_handle)
+
+ def __repr__(self):
+ if self.named_type_class == NamedTypeReferenceClass.TypedefNamedTypeClass:
+ return f"<named type: {self}>"
+ if self.named_type_class == NamedTypeReferenceClass.StructNamedTypeClass:
+ return f"<named type: {self}>"
+ if self.named_type_class == NamedTypeReferenceClass.UnionNamedTypeClass:
+ return f"<named type: {self}>"
+ if self.named_type_class == NamedTypeReferenceClass.EnumNamedTypeClass:
+ return f"<named type: {self}>"
+ return "<named type: unknown >"
+
+ def __str__(self):
+ name = self.registered_name
+ if name is None:
+ name = ""
+ else:
+ name = " " + str(name.name)
+ return f"{self.get_string_before_name()}{name}{self.get_string_after_name()}"
+
+ def __eq__(self, other):
+ if not isinstance(other, self.__class__):
+ return NotImplemented
+ assert other.handle is not None
+ return ctypes.addressof(self.ntr_handle.contents) == ctypes.addressof(other.handle.contents)
+
+ def __ne__(self, other):
+ if not isinstance(other, self.__class__):
+ return NotImplemented
+ return not (self == other)
+
+ def __hash__(self):
+ return hash(ctypes.addressof(self.ntr_handle.contents))
+
+ @property
+ def named_type_class(self) -> NamedTypeReferenceClass:
+ return NamedTypeReferenceClass(core.BNGetTypeReferenceClass(self.ntr_handle))
+
+ @property
+ def type_id(self) -> str:
+ return core.BNGetTypeReferenceId(self.ntr_handle)
+
+ @property
+ def name(self) -> QualifiedName:
+ name = core.BNGetTypeReferenceName(self.ntr_handle)
+ result = QualifiedName._from_core_struct(name)
+ core.BNFreeQualifiedName(name)
+ return result
+
+ @staticmethod
+ def generate_auto_type_ref(type_class, source, name):
+ type_id = RegisteredNameType.generate_auto_type_id(source, name)
+ return NamedTypeReferenceType.create(type_class, type_id, name)
+
+ @staticmethod
+ def generate_auto_demangled_type_ref(type_class, name):
+ type_id = RegisteredNameType.generate_auto_demangled_type_id(name)
+ return NamedTypeReferenceType.create(type_class, type_id, name)
+
+ def target(self, bv:'binaryview.BinaryView') -> Optional[Type]:
+ return bv.get_type_by_id(self.type_id)
+
+
+# class TypedefType(NamedTypeReferenceType):
+# def __init__(self, handle, platform:'_platform.Platform'=None, confidence:int=core.max_confidence):
+# super(TypedefType,).__init__(handle, platform, confidence)
+
+# @classmethod
+# def create(cls, guid:Optional[str],
+# name:QualifiedName, alignment:int=None, width:int=None, platform:'_platform.Platform'=None,
+# confidence:int=core.max_confidence) -> 'TypedefType'
+# return cls(core_type, platform, confidence)
+
+
+@dataclass
+class WideChar(Integer):
+ def immutable_copy(self, platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'WideCharType':
+ return WideCharType.create(self.width, self.altname, platform, confidence)
+
+
+class WideCharType(Type):
+ @classmethod
+ def create(cls, width:int, altname:str="", platform:'_platform.Platform'=None, confidence:int=core.max_confidence) -> 'WideCharType':
+ """
+ ``wide_char`` class method for creating wide char Types.
+
+ :param int width: width of the wide character in bytes
+ :param str altname: alternate name for type
+ """
+ core_type = core.BNCreateWideCharType(width, altname)
+ assert core_type is not None, "core.BNCreateWideCharType returned None"
+ return cls(core.BNNewTypeReference(core_type), platform, confidence)
+
+Types = {
+ TypeClass.VoidTypeClass:VoidType,
+ TypeClass.BoolTypeClass:BoolType,
+ TypeClass.IntegerTypeClass:IntegerType,
+ TypeClass.FloatTypeClass:FloatType,
+ TypeClass.StructureTypeClass:StructureType,
+ TypeClass.EnumerationTypeClass:EnumerationType,
+ TypeClass.PointerTypeClass:PointerType,
+ TypeClass.ArrayTypeClass:ArrayType,
+ TypeClass.FunctionTypeClass:FunctionType,
+ TypeClass.NamedTypeReferenceClass:NamedTypeReferenceType,
+ TypeClass.WideCharTypeClass:WideCharType,
+}
+
+MutableTypes = {
+ TypeClass.VoidTypeClass:Void,
+ TypeClass.BoolTypeClass:Bool,
+ TypeClass.IntegerTypeClass:Integer,
+ TypeClass.FloatTypeClass:Float,
+ TypeClass.StructureTypeClass:Structure,
+ TypeClass.EnumerationTypeClass:Enumeration,
+ TypeClass.PointerTypeClass:Pointer,
+ TypeClass.ArrayTypeClass:Array,
+ TypeClass.FunctionTypeClass:Function,
+ TypeClass.NamedTypeReferenceClass:NamedTypeReference,
+ TypeClass.WideCharTypeClass:WideChar,
+}
+
+
+@dataclass(frozen=True)
+class RegisterSet:
+ regs:List['architecture.RegisterName']
+ confidence:int=core.max_confidence
+
+ def __iter__(self) -> Generator['architecture.RegisterName', None, None]:
+ for reg in self.regs:
+ yield reg
+
+ def __getitem__(self, idx):
+ return self.regs[idx]
+
+ def __len__(self):
+ return len(self.regs)
+
+ def with_confidence(self, confidence):
+ return RegisterSet(list(self.regs), confidence=confidence)
+
+
- def mutable_copy(self):
- if self._mutable:
- return Enumeration(core.BNDuplicateEnumerationBuilder(self._handle))
- return Enumeration(core.BNCreateEnumerationBuilderFromEnumeration(self._handle))
@dataclass(frozen=True)
@@ -1393,7 +2043,7 @@ class TypeParserResult:
functions:Mapping[QualifiedName, Type]
def __repr__(self):
- return "<types: %s, variables: %s, functions: %s>" % (self.types, self.variables, self.functions)
+ return f"<types: {self.types}, variables: {self.variables}, functions: {self.functions}>"
def preprocess_source(source:str, filename:str=None, include_dirs:List[str]=[]) -> Tuple[Optional[str], str]:
@@ -1434,7 +2084,7 @@ def preprocess_source(source:str, filename:str=None, include_dirs:List[str]=[])
@dataclass(frozen=True)
class TypeFieldReference:
- func:Optional['function.Function']
+ func:Optional['_function.Function']
arch:Optional['architecture.Architecture']
address:int
size:int