diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/settings.py | 2 | ||||
| -rw-r--r-- | python/types.py | 395 |
2 files changed, 286 insertions, 111 deletions
diff --git a/python/settings.py b/python/settings.py index fec4023d..f81c8eef 100644 --- a/python/settings.py +++ b/python/settings.py @@ -65,7 +65,7 @@ class Settings(object): def __init__(self, instance_id = "default", handle = None): if handle is None: - if instance_id is None or instance_id is "": + if instance_id is None or instance_id == "": instance_id = "default" self._instance_id = instance_id if instance_id == "default": diff --git a/python/types.py b/python/types.py index ed4360d6..720f8568 100644 --- a/python/types.py +++ b/python/types.py @@ -320,12 +320,16 @@ class FunctionParameter(object): class Type(object): def __init__(self, handle, platform = None, confidence = max_confidence): - self.handle = handle + self._handle = handle + self._mutable = isinstance(handle.contents, core.BNTypeBuilder) self._confidence = confidence self._platform = platform def __del__(self): - core.BNFreeType(self.handle) + if self._mutable: + core.BNFreeTypeBuilder(self._handle) + else: + core.BNFreeType(self._handle) def __eq__(self, value): if not isinstance(value, Type): @@ -338,51 +342,101 @@ class Type(object): return core.BNTypesNotEqual(self.handle, value.handle) @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): """Type class (read-only)""" - return TypeClass(core.BNGetTypeClass(self.handle)) + if self._mutable: + return TypeClass(core.BNGetTypeBuilderClass(self._handle)) + return TypeClass(core.BNGetTypeClass(self._handle)) @property def width(self): """Type width (read-only)""" - return core.BNGetTypeWidth(self.handle) + if self._mutable: + return core.BNGetTypeBuilderWidth(self._handle) + return core.BNGetTypeWidth(self._handle) @property def alignment(self): """Type alignment (read-only)""" - return core.BNGetTypeAlignment(self.handle) + if self._mutable: + return core.BNGetTypeBuilderAlignment(self._handle) + return core.BNGetTypeAlignment(self._handle) @property def signed(self): """Wether type is signed (read-only)""" - result = core.BNIsTypeSigned(self.handle) + 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)""" - result = core.BNIsTypeConst(self.handle) + 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 = 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 = max_confidence - core.BNTypeSetConst(self.handle, bc) + core.BNTypeBuilderSetVolatile(self._handle, bc) @property - def modified(self): - """Whether type is modified (read-only)""" - return core.BNIsTypeFloatingPoint(self.handle) + 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)""" - result = core.BNGetChildType(self.handle) + 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) @@ -390,7 +444,10 @@ class Type(object): @property def element_type(self): """Target (read-only)""" - result = core.BNGetChildType(self.handle) + 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) @@ -398,7 +455,10 @@ class Type(object): @property def return_value(self): """Return value (read-only)""" - result = core.BNGetChildType(self.handle) + 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) @@ -406,7 +466,10 @@ class Type(object): @property def calling_convention(self): """Calling convention (read-only)""" - result = core.BNGetTypeCallingConvention(self.handle) + if self._mutable: + result = core.BNGetTypeBuilderCallingConvention(self._handle) + else: + result = core.BNGetTypeCallingConvention(self._handle) if not result.convention: return None return binaryninja.callingconvention.CallingConvention(None, handle = result.convention, confidence = result.confidence) @@ -415,7 +478,10 @@ class Type(object): def parameters(self): """Type parameters list (read-only)""" count = ctypes.c_ulonglong() - params = core.BNGetTypeParameters(self.handle, count) + if self._mutable: + params = core.BNGetTypeBuilderParameters(self._handle, count) + else: + params = core.BNGetTypeParameters(self._handle, count) result = [] for i in range(0, count.value): param_type = Type(core.BNNewTypeReference(params[i].type), platform = self._platform, confidence = params[i].typeConfidence) @@ -436,19 +502,28 @@ class Type(object): @property def has_variable_arguments(self): """Whether type has variable arguments (read-only)""" - result = core.BNTypeHasVariableArguments(self.handle) + 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 (read-only)""" - result = core.BNFunctionTypeCanReturn(self.handle) + if self._mutable: + result = core.BNFunctionTypeBuilderCanReturn(self._handle) + else: + result = core.BNFunctionTypeCanReturn(self._handle) return BoolWithConfidence(result.value, confidence = result.confidence) @property def structure(self): """Structure of the type (read-only)""" - result = core.BNGetTypeStructure(self.handle) + if self._mutable: + result = core.BNGetTypeBuilderStructure(self._handle) + else: + result = core.BNGetTypeStructure(self._handle) if result is None: return None return Structure(result) @@ -456,7 +531,10 @@ class Type(object): @property def enumeration(self): """Type enumeration (read-only)""" - result = core.BNGetTypeEnumeration(self.handle) + if self._mutable: + result = core.BNGetTypeBuilderEnumeration(self._handle) + else: + result = core.BNGetTypeEnumeration(self._handle) if result is None: return None return Enumeration(result) @@ -464,7 +542,10 @@ class Type(object): @property def named_type_reference(self): """Reference to a named type (read-only)""" - result = core.BNGetTypeNamedTypeReference(self.handle) + if self._mutable: + result = core.BNGetTypeBuilderNamedTypeReference(self._handle) + else: + result = core.BNGetTypeNamedTypeReference(self._handle) if result is None: return None return NamedTypeReference(handle = result) @@ -472,17 +553,24 @@ class Type(object): @property def count(self): """Type count (read-only)""" - return core.BNGetTypeElementCount(self.handle) + if self._mutable: + return core.BNGetTypeBuilderElementCount(self._handle) + return core.BNGetTypeElementCount(self._handle) @property def offset(self): """Offset into structure (read-only)""" - return core.BNGetTypeOffset(self.handle) + if self._mutable: + return core.BNGetTypeBuilderOffset(self._handle) + return core.BNGetTypeOffset(self._handle) @property def stack_adjustment(self): """Stack adjustment for function (read-only)""" - result = core.BNGetTypeStackAdjustment(self.handle) + if self._mutable: + result = core.BNGetTypeBuilderStackAdjustment(self._handle) + else: + result = core.BNGetTypeStackAdjustment(self._handle) return SizeWithConfidence(result.value, confidence = result.confidence) def __len__(self): @@ -492,7 +580,9 @@ class Type(object): platform = None if self._platform is not None: platform = self._platform.handle - return core.BNGetTypeString(self.handle, platform) + if self._mutable: + return core.BNGetTypeBuilderString(self._handle, platform) + return core.BNGetTypeString(self._handle, platform) def __repr__(self): if self._confidence < max_confidence: @@ -503,13 +593,17 @@ class Type(object): platform = None if self._platform is not None: platform = self._platform.handle - return core.BNGetTypeStringBeforeName(self.handle, platform) + if self._mutable: + return core.BNGetTypeBuilderStringBeforeName(self._handle, platform) + return core.BNGetTypeStringBeforeName(self._handle, platform) def get_string_after_name(self): platform = None if self._platform is not None: platform = self._platform.handle - return core.BNGetTypeStringAfterName(self.handle, platform) + if self._mutable: + return core.BNGetTypeBuilderStringAfterName(self._handle, platform) + return core.BNGetTypeStringAfterName(self._handle, platform) @property def tokens(self): @@ -521,7 +615,10 @@ class Type(object): platform = None if self._platform is not None: platform = self._platform.handle - tokens = core.BNGetTypeTokens(self.handle, platform, base_confidence, count) + if self._mutable: + tokens = core.BNGetTypeBuilderTokens(self._handle, platform, base_confidence, count) + else: + tokens = core.BNGetTypeTokens(self._handle, platform, base_confidence, count) result = binaryninja.function.InstructionTextToken.get_instruction_lines(tokens, count.value) core.BNFreeInstructionText(tokens, count.value) return result @@ -531,7 +628,10 @@ class Type(object): platform = None if self._platform is not None: platform = self._platform.handle - tokens = core.BNGetTypeTokensBeforeName(self.handle, platform, base_confidence, count) + if self._mutable: + tokens = core.BNGetTypeBuilderTokensBeforeName(self._handle, platform, base_confidence, count) + else: + tokens = core.BNGetTypeTokensBeforeName(self._handle, platform, base_confidence, count) result = binaryninja.function.InstructionTextToken.get_instruction_lines(tokens, count.value) core.BNFreeInstructionText(tokens, count.value) return result @@ -541,18 +641,21 @@ class Type(object): platform = None if self._platform is not None: platform = self._platform.handle - tokens = core.BNGetTypeTokensAfterName(self.handle, platform, base_confidence, count) + if self._mutable: + tokens = core.BNGetTypeBuilderTokensAfterName(self._handle, platform, base_confidence, count) + else: + tokens = core.BNGetTypeTokensAfterName(self._handle, platform, base_confidence, count) result = binaryninja.function.InstructionTextToken.get_instruction_lines(tokens, count.value) core.BNFreeInstructionText(tokens, count.value) return result @classmethod def void(cls): - return Type(core.BNCreateVoidType()) + return Type(core.BNCreateVoidTypeBuilder()) @classmethod def bool(self): - return Type(core.BNCreateBoolType()) + return Type(core.BNCreateBoolTypeBuilder()) @classmethod def char(self): @@ -576,7 +679,7 @@ class Type(object): sign_conf.value = sign.value sign_conf.confidence = sign.confidence - return Type(core.BNCreateIntegerType(width, sign_conf, altname)) + return Type(core.BNCreateIntegerTypeBuilder(width, sign_conf, altname)) @classmethod def float(self, width, altname=""): @@ -586,40 +689,40 @@ class Type(object): :param int width: width of the floating point number in bytes :param str altname: alternate name for type """ - return Type(core.BNCreateFloatType(width, altname)) + return Type(core.BNCreateFloatTypeBuilder(width, altname)) @classmethod def structure_type(self, structure_type): - return Type(core.BNCreateStructureType(structure_type.handle)) + return Type(core.BNCreateStructureTypeBuilder(structure_type.handle)) @classmethod def named_type(self, named_type, width = 0, align = 1): - return Type(core.BNCreateNamedTypeReference(named_type.handle, width, align)) + return Type(core.BNCreateNamedTypeReferenceBuilder(named_type.handle, width, align)) @classmethod def named_type_from_type_and_id(self, type_id, name, t): name = QualifiedName(name)._get_core_struct() if t is not None: t = t.handle - return Type(core.BNCreateNamedTypeReferenceFromTypeAndId(type_id, name, t)) + return Type(core.BNCreateNamedTypeReferenceBuilderFromTypeAndId(type_id, name, t)) @classmethod def named_type_from_type(self, name, t): name = QualifiedName(name)._get_core_struct() if t is not None: t = t.handle - return Type(core.BNCreateNamedTypeReferenceFromTypeAndId("", name, t)) + return Type(core.BNCreateNamedTypeReferenceBuilderFromTypeAndId("", name, t)) @classmethod def named_type_from_registered_type(self, view, name): name = QualifiedName(name)._get_core_struct() - return Type(core.BNCreateNamedTypeReferenceFromType(view.handle, name)) + return Type(core.BNCreateNamedTypeReferenceBuilderFromType(view.handle, name)) @classmethod def enumeration_type(self, arch, e, width=None, sign=False): if width is None: width = arch.default_int_size - return Type(core.BNCreateEnumerationType(arch.handle, e.handle, width, sign)) + return Type(core.BNCreateEnumerationTypeBuilder(arch.handle, e.handle, width, sign)) @classmethod def pointer(self, arch, t, const=None, volatile=None, ref_type=None): @@ -648,14 +751,14 @@ class Type(object): volatile_conf.value = volatile.value volatile_conf.confidence = volatile.confidence - return Type(core.BNCreatePointerType(arch.handle, type_conf, const_conf, volatile_conf, ref_type)) + return Type(core.BNCreatePointerTypeBuilder(arch.handle, type_conf, const_conf, volatile_conf, ref_type)) @classmethod def array(self, t, count): type_conf = core.BNTypeWithConfidence() type_conf.type = t.handle type_conf.confidence = t.confidence - return Type(core.BNCreateArrayType(type_conf, count)) + return Type(core.BNCreateArrayTypeBuilder(type_conf, count)) @classmethod def function(self, ret, params, calling_convention=None, variable_arguments=None, stack_adjust=None): @@ -722,7 +825,7 @@ class Type(object): stack_adjust_conf.value = stack_adjust.value stack_adjust_conf.confidence = stack_adjust.confidence - return Type(core.BNCreateFunctionType(ret_conf, conv_conf, param_buf, len(params), + return Type(core.BNCreateFunctionTypeBuilder(ret_conf, conv_conf, param_buf, len(params), vararg_conf, stack_adjust_conf)) @classmethod @@ -742,12 +845,6 @@ class Type(object): def with_confidence(self, confidence): return Type(handle = core.BNNewTypeReference(self.handle), platform = self._platform, confidence = confidence) - def __setattr__(self, name, value): - try: - object.__setattr__(self, name, value) - except AttributeError: - raise AttributeError("attribute '%s' is read only" % name) - @property def confidence(self): """ """ @@ -766,6 +863,20 @@ class Type(object): def platform(self, value): self._platform = value + 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)) + + def with_replaced_enumeration(self, from_enum, to_enum): + return Type(handle = core.BNTypeWithReplacedEnumeration(self.handle, from_enum.handle, to_enum.handle)) + + def with_replaced_named_type_reference(self, from_ref, to_ref): + return Type(handle = core.BNTypeWithReplacedNamedTypeReference(self.handle, from_ref.handle, to_ref.handle)) + class BoolWithConfidence(object): def __init__(self, value, confidence = max_confidence): @@ -942,13 +1053,9 @@ class ReferenceTypeWithConfidence(object): class NamedTypeReference(object): def __init__(self, type_class = NamedTypeReferenceClass.UnknownNamedTypeClass, type_id = None, name = None, handle = None): if handle is None: - self.handle = core.BNCreateNamedType() - core.BNSetTypeReferenceClass(self.handle, type_class) - if type_id is not None: - core.BNSetTypeReferenceId(self.handle, type_id) if name is not None: name = QualifiedName(name)._get_core_struct() - core.BNSetTypeReferenceName(self.handle, name) + self.handle = core.BNCreateNamedType(type_class, type_id, name) else: self.handle = handle @@ -969,18 +1076,10 @@ class NamedTypeReference(object): def type_class(self): return NamedTypeReferenceClass(core.BNGetTypeReferenceClass(self.handle)) - @type_class.setter - def type_class(self, value): - core.BNSetTypeReferenceClass(self.handle, value) - @property def type_id(self): return core.BNGetTypeReferenceId(self.handle) - @type_id.setter - def type_id(self, value): - core.BNSetTypeReferenceId(self.handle, value) - @property def name(self): name = core.BNGetTypeReferenceName(self.handle) @@ -988,11 +1087,6 @@ class NamedTypeReference(object): core.BNFreeQualifiedName(name) return result - @name.setter - def name(self, value): - value = QualifiedName(value)._get_core_struct() - core.BNSetTypeReferenceName(self.handle, value) - def __repr__(self): if self.type_class == NamedTypeReferenceClass.TypedefNamedTypeClass: return "<named type: typedef %s>" % str(self.name) @@ -1058,26 +1152,34 @@ class StructureMember(object): class Structure(object): def __init__(self, handle=None): if handle is None: - self.handle = core.BNCreateStructure() + self._handle = core.BNCreateStructureBuilder() + self._mutable = True else: - self.handle = handle + self._handle = handle + self._mutable = isinstance(handle.contents, core.BNStructureBuilder) def __del__(self): - core.BNFreeStructure(self.handle) + if self._mutable: + core.BNFreeStructureBuilder(self._handle) + else: + core.BNFreeStructure(self._handle) def __eq__(self, value): if not isinstance(value, Structure): return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + return ctypes.addressof(self._handle.contents) == ctypes.addressof(value._handle.contents) def __ne__(self, value): if not isinstance(value, Structure): return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + return ctypes.addressof(self._handle.contents) != ctypes.addressof(value._handle.contents) def __getitem__(self, name): try: - member = core.BNGetStructureMemberByName(self.handle, name) + if self._mutable: + member = core.BNGetStructureBuilderMemberByName(self._handle, name) + else: + member = core.BNGetStructureMemberByName(self._handle, name) return StructureMember(Type(core.BNNewTypeReference(member.contents.type), confidence=member.contents.typeConfidence), member.contents.name, member.contents.offset) finally: @@ -1085,17 +1187,33 @@ class Structure(object): def member_at_offset(self, offset): try: - member = core.BNGetStructureMemberAtOffset(self.handle, offset) + if self._mutable: + member = core.BNGetStructureBuilderMemberAtOffset(self._handle, offset, None) + else: + member = core.BNGetStructureMemberAtOffset(self._handle, offset, None) return StructureMember(Type(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) + 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() - members = core.BNGetStructureMembers(self.handle, count) + if self._mutable: + members = core.BNGetStructureBuilderMembers(self._handle, count) + else: + members = core.BNGetStructureMembers(self._handle, count) try: result = [] for i in range(0, count.value): @@ -1108,70 +1226,104 @@ class Structure(object): @property def width(self): """Structure width""" - return core.BNGetStructureWidth(self.handle) + if self._mutable: + return core.BNGetStructureBuilderWidth(self._handle) + return core.BNGetStructureWidth(self._handle) @width.setter def width(self, new_width): - core.BNSetStructureWidth(self.handle, new_width) + if not self._mutable: + raise AttributeError("Finalized Structure object is immutable, use mutable_copy()") + core.BNSetStructureBuilderWidth(self._handle, new_width) @property def alignment(self): """Structure alignment""" - return core.BNGetStructureAlignment(self.handle) + if self._mutable: + return core.BNGetStructureBuilderAlignment(self._handle) + return core.BNGetStructureAlignment(self._handle) @alignment.setter def alignment(self, align): - core.BNSetStructureAlignment(self.handle, align) + if not self._mutable: + raise AttributeError("Finalized Structure object is immutable, use mutable_copy()") + core.BNSetStructureBuilderAlignment(self._handle, align) @property def packed(self): - return core.BNIsStructurePacked(self.handle) + if self._mutable: + return core.BNIsStructureBuilderPacked(self._handle) + return core.BNIsStructurePacked(self._handle) @packed.setter def packed(self, value): - core.BNSetStructurePacked(self.handle, value) + if not self._mutable: + raise AttributeError("Finalized Structure object is immutable, use mutable_copy()") + core.BNSetStructureBuilderPacked(self._handle, value) @property def union(self): - return core.BNIsStructureUnion(self.handle) + if self._mutable: + return core.BNIsStructureBuilderUnion(self._handle) + return core.BNIsStructureUnion(self._handle) @property def type(self): - return StructureType(core.BNGetStructureType(self.handle)) + if self._mutable: + return StructureType(core.BNGetStructureBuilderType(self._handle)) + return StructureType(core.BNGetStructureType(self._handle)) @type.setter def type(self, value): - core.BNSetStructureType(self.handle, value) - - def __setattr__(self, name, value): - try: - object.__setattr__(self, name, value) - except AttributeError: - raise AttributeError("attribute '%s' is read only" % name) + if not self._mutable: + raise AttributeError("Finalized Structure object is immutable, use mutable_copy()") + core.BNSetStructureBuilderType(self._handle, value) def __repr__(self): return "<struct: size %#x>" % self.width 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.BNAddStructureMember(self.handle, tc, name) + core.BNAddStructureBuilderMember(self._handle, tc, name) def insert(self, offset, 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.BNAddStructureMemberAtOffset(self.handle, tc, name, offset) + core.BNAddStructureBuilderMemberAtOffset(self._handle, tc, name, offset) def remove(self, i): - core.BNRemoveStructureMember(self.handle, i) + if not self._mutable: + raise AttributeError("Finalized Structure object is immutable, use mutable_copy()") + core.BNRemoveStructureBuilderMember(self._handle, i) def replace(self, i, 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.BNReplaceStructureMember(self.handle, i, tc, name) + core.BNReplaceStructureBuilderMember(self._handle, i, tc, name) + + def mutable_copy(self): + if self._mutable: + return Structure(core.BNDuplicateStructureBuilder(self._handle)) + return Structure(core.BNCreateStructureBuilderFromStructure(self._handle)) + + def with_replaced_structure(self, from_struct, to_struct): + return Structure(core.BNStructureWithReplacedStructure(self.handle, from_struct.handle, to_struct.handle)) + + def with_replaced_enumeration(self, from_enum, to_enum): + return Structure(core.BNStructureWithReplacedEnumeration(self.handle, from_enum.handle, to_enum.handle)) + + def with_replaced_named_type_reference(self, from_ref, to_ref): + return Structure(core.BNStructureWithReplacedNamedTypeReference(self.handle, from_ref.handle, to_ref.handle)) class EnumerationMember(object): @@ -1214,54 +1366,77 @@ class EnumerationMember(object): class Enumeration(object): def __init__(self, handle=None): if handle is None: - self.handle = core.BNCreateEnumeration() + self._handle = core.BNCreateEnumerationBuilder() + self._mutable = True else: - self.handle = handle + self._handle = handle + self._mutable = isinstance(handle.contents, core.BNEnumerationBuilder) def __del__(self): - core.BNFreeEnumeration(self.handle) + if self._mutable: + core.BNFreeEnumerationBuilder(self._handle) + else: + core.BNFreeEnumeration(self._handle) def __eq__(self, value): if not isinstance(value, Enumeration): return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + return ctypes.addressof(self._handle.contents) == ctypes.addressof(value._handle.contents) def __ne__(self, value): if not isinstance(value, Enumeration): return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + return ctypes.addressof(self._handle.contents) != ctypes.addressof(value._handle.contents) + + @property + def handle(self): + if self._mutable: + # First use of a mutable Enumeration makes it immutable + finalized = core.BNFinalizeEnumerationBuilder(self._handle) + core.BNFreeEnumerationBuilder(self._handle) + self._handle = finalized + self._mutable = False + return self._handle @property def members(self): """Enumeration member list (read-only)""" count = ctypes.c_ulonglong() - members = core.BNGetEnumerationMembers(self.handle, count) + if self._mutable: + members = core.BNGetEnumerationBuilderMembers(self._handle, count) + else: + members = core.BNGetEnumerationMembers(self._handle, count) result = [] for i in range(0, count.value): result.append(EnumerationMember(members[i].name, members[i].value, members[i].isDefault)) core.BNFreeEnumerationMemberList(members, count.value) return result - def __setattr__(self, name, value): - try: - object.__setattr__(self, name, value) - except AttributeError: - raise AttributeError("attribute '%s' is read only" % name) - def __repr__(self): return "<enum: %s>" % repr(self.members) 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.BNAddEnumerationMember(self.handle, name) + core.BNAddEnumerationBuilderMember(self._handle, name) else: - core.BNAddEnumerationMemberWithValue(self.handle, name, value) + core.BNAddEnumerationBuilderMemberWithValue(self._handle, name, value) def remove(self, i): - core.BNRemoveEnumerationMember(self.handle, i) + if not self._mutable: + raise AttributeError("Finalized Enumeration object is immutable, use mutable_copy()") + core.BNRemoveEnumerationBuilderMember(self._handle, i) def replace(self, i, name, value): - core.BNReplaceEnumerationMember(self.handle, i, name, value) + if not self._mutable: + raise AttributeError("Finalized Enumeration object is immutable, use mutable_copy()") + core.BNReplaceEnumerationBuilderMember(self._handle, i, name, value) + + def mutable_copy(self): + if self._mutable: + return Enumeration(core.BNDuplicateEnumerationBuilder(self._handle)) + return Enumeration(core.BNCreateEnumerationBuilderFromEnumeration(self._handle)) class TypeParserResult(object): |
