From 8f1bc5944b849f3ad0cbbd5972d5ab9948ed4d57 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Sat, 2 May 2020 11:01:35 -0400 Subject: Fix up equality operators and had hash operators --- python/architecture.py | 95 ++++---- python/basicblock.py | 64 +++--- python/binaryview.py | 529 +++++++++++++++++++++++--------------------- python/callingconvention.py | 31 +-- python/filemetadata.py | 42 ++-- python/flowgraph.py | 138 ++++++------ python/function.py | 193 ++++++++++------ python/highlevelil.py | 83 ++++--- python/lineardisassembly.py | 175 ++++++++------- python/lowlevelil.py | 386 ++++++++++++++++++++------------ python/mediumlevelil.py | 202 ++++++++--------- python/metadata.py | 277 +++++++++++------------ python/platform.py | 74 +++---- python/scriptingprovider.py | 12 +- python/settings.py | 18 +- python/transform.py | 19 +- python/types.py | 263 +++++++++++++--------- 17 files changed, 1432 insertions(+), 1169 deletions(-) (limited to 'python') diff --git a/python/architecture.py b/python/architecture.py index ad295c91..8495255c 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -79,12 +79,6 @@ class _ArchitectureMetaClass(type): cls._registered_cb = arch._cb arch.handle = core.BNRegisterArchitecture(cls.name, arch._cb) - def __setattr__(self, name, value): - try: - type.__setattr__(self, name, value) - except AttributeError: - raise AttributeError("attribute '%s' is read only" % name) - class Architecture(with_metaclass(_ArchitectureMetaClass, object)): """ @@ -387,15 +381,32 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): self._pending_name_and_type_lists = {} self._pending_type_lists = {} - def __eq__(self, value): - if not isinstance(value, Architecture): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + def __repr__(self): + return "" % self.name - def __ne__(self, value): - if not isinstance(value, Architecture): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.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.handle.contents)) + + def __setattr__(self, name, value): + if ((name == "name") or (name == "endianness") or (name == "address_size") or + (name == "default_int_size") or (name == "regs") or (name == "get_max_instruction_length") or + (name == "get_instruction_alignment")): + raise AttributeError("attribute '%s' is read only" % name) + else: + try: + object.__setattr__(self, name, value) + except AttributeError: + raise AttributeError("attribute '%s' is read only" % name) @property def list(self): @@ -442,21 +453,6 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): core.BNFreeTypeLibraryList(handles, count.value) return result - - def __setattr__(self, name, value): - if ((name == "name") or (name == "endianness") or (name == "address_size") or - (name == "default_int_size") or (name == "regs") or (name == "get_max_instruction_length") or - (name == "get_instruction_alignment")): - raise AttributeError("attribute '%s' is read only" % name) - else: - try: - object.__setattr__(self, name, value) - except AttributeError: - raise AttributeError("attribute '%s' is read only" % name) - - def __repr__(self): - return "" % self.name - def _init(self, ctxt, handle): self.handle = handle @@ -2749,15 +2745,38 @@ class ReferenceSource(object): else: return "" % self._address - def __eq__(self, value): - if not isinstance(value, ReferenceSource): - return False - return self.function == value.function and self.arch == value.arch and self.address == value.address - - def __lt__(self, value): - if not isinstance(value, ReferenceSource): - raise TypeError("Can only compare to other ReferenceSource objects") - return self.address < value.address + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return (self.function, self.arch, self.address) == (other.address, other.function, other.arch) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __lt__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.address < other.address + + def __gt__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.address > other.address + + def __gt__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.address >= other.address + + def __le__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.address <= other.address + + def __hash__(self): + hash((self._function, self._arch, self._address)) @property def function(self): diff --git a/python/basicblock.py b/python/basicblock.py index bfd80387..5bcf6aff 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -39,14 +39,6 @@ class BasicBlockEdge(object): self._back_edge = back_edge self._fall_through = fall_through - def __eq__(self, value): - if not isinstance(value, BasicBlockEdge): - return False - return (self._type, self._source, self._target, self._back_edge, self._fall_through) == (value.type, value.source, value.target, value.back_edge, value.fall_through) - - def __hash__(self): - return hash((self._type, self._source, self._target, self.back_edge, self.fall_through)) - def __repr__(self): if self._type == BranchType.UnresolvedBranch: return "<%s>" % BranchType(self._type).name @@ -55,6 +47,20 @@ class BasicBlockEdge(object): else: return "<%s: %#x>" % (BranchType(self._type).name, self._target.start) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return (self._type, self._source, self._target, self._back_edge, self._fall_through) == \ + (other._type, other._source, other._target, other._back_edge, other._fall_through) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash((self._type, self._source, self._target, self.back_edge, self.fall_through)) + @property def type(self): """ """ @@ -114,15 +120,28 @@ class BasicBlock(object): def __del__(self): core.BNFreeBasicBlock(self.handle) - def __eq__(self, value): - if not isinstance(value, BasicBlock): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + def __repr__(self): + arch = self.arch + if arch: + return "" % (arch.name, self.start, self.end) + else: + return "" % (self.start, self.end) + + def __len__(self): + return int(core.BNGetBasicBlockLength(self.handle)) - def __ne__(self, value): - if not isinstance(value, BasicBlock): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.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((self.start, self.end, self.arch.name)) def __setattr__(self, name, value): try: @@ -130,16 +149,6 @@ class BasicBlock(object): except AttributeError: raise AttributeError("attribute '%s' is read only" % name) - def __len__(self): - return int(core.BNGetBasicBlockLength(self.handle)) - - def __repr__(self): - arch = self.arch - if arch: - return "" % (arch.name, self.start, self.end) - else: - return "" % (self.start, self.end) - def __iter__(self): if self._instStarts is None: # don't and instruction start cache the object is likely ephemeral @@ -165,9 +174,6 @@ class BasicBlock(object): data = self._view.read(start, length) return self.arch.get_instruction_text(data, start) - def __hash__(self): - return hash((self.start, self.end, self.arch.name)) - def _buildStartCache(self): if self._instStarts is None: # build the instruction start cache diff --git a/python/binaryview.py b/python/binaryview.py index 61500f06..fe94b0bf 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -137,13 +137,8 @@ class StringReference(object): self._length = length self._view = bv - @property - def value(self): - return self._view.read(self._start, self._length).decode(_decodings[self._type]) - - @property - def raw(self): - return self._view.read(self._start, self._length) + def __repr__(self): + return "<%s: %#x, len %#x>" % (self._type, self._start, self._length) def __str__(self): return pyNativeStr(self.raw) @@ -151,8 +146,13 @@ class StringReference(object): def __len__(self): return self._length - def __repr__(self): - return "<%s: %#x, len %#x>" % (self._type, self._start, self._length) + @property + def value(self): + return self._view.read(self._start, self._length).decode(_decodings[self._type]) + + @property + def raw(self): + return self._view.read(self._start, self._length) @property def type(self): @@ -694,15 +694,21 @@ class BinaryViewType(with_metaclass(_BinaryViewTypeMetaclass, object)): def __init__(self, handle): self.handle = core.handle_of_type(handle, core.BNBinaryViewType) - def __eq__(self, value): - if not isinstance(value, BinaryViewType): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + def __repr__(self): + return "" % self.name - def __ne__(self, value): - if not isinstance(value, BinaryViewType): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.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.handle.contents)) @property def list(self): @@ -719,9 +725,6 @@ class BinaryViewType(with_metaclass(_BinaryViewTypeMetaclass, object)): """BinaryView long name (read-only)""" return core.BNGetBinaryViewTypeLongName(self.handle) - def __repr__(self): - return "" % self.name - def create(self, data): view = core.BNCreateBinaryViewOfType(self.handle, data.handle) if view is None: @@ -902,6 +905,31 @@ class Segment(object): def __init__(self, handle): self.handle = handle + def __del__(self): + core.BNFreeSegment(self.handle) + + def __repr__(self): + return "" % (self.start, self.end, + "r" if self.readable else "-", + "w" if self.writable else "-", + "x" if self.executable else "-") + + def __len__(self): + return core.BNSegmentGetLength(self.handle) + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.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.handle.contents)) + @property def start(self): return core.BNSegmentGetStart(self.handle) @@ -965,36 +993,34 @@ class Segment(object): core.BNFreeRelocationRanges(ranges, count) return result + + +class Section(object): + def __init__(self, handle): + self.handle = core.handle_of_type(handle, core.BNSection) + def __del__(self): - core.BNFreeSegment(self.handle) + core.BNFreeSection(self.handle) + + def __repr__(self): + return "
" % (self.name, self.start, self.end) + + def __len__(self): + return core.BNSectionGetLength(self.handle) def __eq__(self, other): - if not isinstance(other, Segment): - return False + if not isinstance(other, self.__class__): + return NotImplemented return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents) def __ne__(self, other): - if not isinstance(other, Segment): - return False - return ctypes.addressof(self.handle.contents) != ctypes.addressof(other.handle.contents) + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) def __hash__(self): return hash(ctypes.addressof(self.handle.contents)) - def __len__(self): - return core.BNSegmentGetLength(self.handle) - - def __repr__(self): - return "" % (self.start, self.end, - "r" if self.readable else "-", - "w" if self.writable else "-", - "x" if self.executable else "-") - - -class Section(object): - def __init__(self, handle): - self.handle = core.handle_of_type(handle, core.BNSection) - @property def name(self): return core.BNSectionGetName(self.handle) @@ -1039,47 +1065,35 @@ class Section(object): def end(self): return self.start + len(self) - def __del__(self): - core.BNFreeSection(self.handle) - - def __eq__(self, other): - if not isinstance(other, Section): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents) - - def __ne__(self, other): - if not isinstance(other, Section): - return False - return ctypes.addressof(self.handle.contents) != ctypes.addressof(other.handle.contents) - - def __hash__(self): - return hash(ctypes.addressof(self.handle.contents)) - - def __len__(self): - return core.BNSectionGetLength(self.handle) - - def __repr__(self): - return "
" % (self.name, self.start, self.end) - class AddressRange(object): def __init__(self, start, end): self._start = start self._end = end + def __repr__(self): + return "<%#x-%#x>" % (self._start, self._end) + def __len__(self): return self._end - self.start + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return (self._start, self._end) == (other._start, other._end) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash((self._start, self._end)) + @property def length(self): return self._end - self._start - def __len__(self): - return self._end - self._start - - def __repr__(self): - return "<%#x-%#x>" % (self._start, self._end) - @property def start(self): """ """ @@ -1103,6 +1117,25 @@ class TagType(object): def __init__(self, handle): self.handle = core.handle_of_type(handle, core.BNTagType) + def __del__(self): + core.BNFreeTagType(self.handle) + + def __repr__(self): + return "" % (self.name, self.icon) + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.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.handle.contents)) + @property def name(self): """Name of the TagType""" @@ -1139,30 +1172,31 @@ class TagType(object): def type(self, value): core.BNTagTypeSetType(self.handle, value) + + +class Tag(object): + def __init__(self, handle): + self.handle = core.handle_of_type(handle, core.BNTag) + def __del__(self): - core.BNFreeTagType(self.handle) + core.BNFreeTag(self.handle) + + def __repr__(self): + return "" % (self.type.icon, self.type.name, self.data) def __eq__(self, other): - if not isinstance(other, TagType): - return False + if not isinstance(other, self.__class__): + return NotImplemented return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents) def __ne__(self, other): - if not isinstance(other, TagType): - return False - return ctypes.addressof(self.handle.contents) != ctypes.addressof(other.handle.contents) + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) def __hash__(self): return hash(ctypes.addressof(self.handle.contents)) - def __repr__(self): - return "" % (self.name, self.icon) - - -class Tag(object): - def __init__(self, handle): - self.handle = core.handle_of_type(handle, core.BNTag) - @property def type(self): return TagType(core.BNTagGetType(self.handle)) @@ -1175,25 +1209,6 @@ class Tag(object): def data(self, value): core.BNTagSetData(self.handle, value) - def __del__(self): - core.BNFreeTag(self.handle) - - def __eq__(self, other): - if not isinstance(other, Tag): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents) - - def __ne__(self, other): - if not isinstance(other, Tag): - return False - return ctypes.addressof(self.handle.contents) != ctypes.addressof(other.handle.contents) - - def __hash__(self): - return hash(self.handle.contents) - - def __repr__(self): - return "" % (self.type.icon, self.type.name, self.data) - class _BinaryViewAssociatedDataStore(associateddatastore._AssociatedDataStore): _defaults = {} @@ -1302,15 +1317,108 @@ class BinaryView(object): self._notifications = {} self._next_address = None # Do NOT try to access view before init() is called, use placeholder - def __eq__(self, value): - if not isinstance(value, BinaryView): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + def __del__(self): + for i in self.notifications.values(): + i._unregister() + core.BNFreeBinaryView(self.handle) + + def __repr__(self): + start = self.start + length = len(self) + if start != 0: + size = "start %#x, len %#x" % (start, length) + else: + size = "len %#x" % length + filename = self._file.filename + if len(filename) > 0: + return "" % (filename, size) + return "" % (size) + + def __len__(self): + return int(core.BNGetViewLength(self.handle)) + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents) - def __ne__(self, value): - if not isinstance(value, BinaryView): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.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.handle.contents)) + + def __iter__(self): + count = ctypes.c_ulonglong(0) + funcs = core.BNGetAnalysisFunctionList(self.handle, count) + try: + for i in range(0, count.value): + yield binaryninja.function.Function(self, core.BNNewFunctionReference(funcs[i])) + finally: + core.BNFreeFunctionList(funcs, count.value) + + + def __getitem__(self, i): + if isinstance(i, tuple): + result = bytes() + for s in i: + result += self.__getitem__(s) + return result + elif isinstance(i, slice): + if i.step is not None: + raise IndexError("step not implemented") + i = i.indices(self.end) + start = i[0] + stop = i[1] + if stop <= start: + return "" + return self.read(start, stop - start) + elif i < 0: + if i >= -len(self): + value = self.read(int(len(self) + i), 1) + if len(value) == 0: + return IndexError("index not readable") + return value + raise IndexError("index out of range") + elif (i >= self.start) and (i < self.end): + value = self.read(int(i), 1) + if len(value) == 0: + return IndexError("index not readable") + return value + else: + raise IndexError("index out of range") + + def __setitem__(self, i, value): + if isinstance(i, slice): + if i.step is not None: + raise IndexError("step not supported on assignment") + i = i.indices(self.end) + start = i[0] + stop = i[1] + if stop < start: + stop = start + if len(value) != (stop - start): + self.remove(start, stop - start) + self.insert(start, value) + else: + self.write(start, value) + elif i < 0: + if i >= -len(self): + if len(value) != 1: + raise ValueError("expected single byte for assignment") + if self.write(int(len(self) + i), value) != 1: + raise IndexError("index not writable") + else: + raise IndexError("index out of range") + elif (i >= self.start) and (i < self.end): + if len(value) != 1: + raise ValueError("expected single byte for assignment") + if self.write(int(i), value) != 1: + raise IndexError("index not writable") + else: + raise IndexError("index out of range") @classmethod def register(cls): @@ -1472,20 +1580,6 @@ class BinaryView(object): for i in block: yield i - def __del__(self): - for i in self.notifications.values(): - i._unregister() - core.BNFreeBinaryView(self.handle) - - def __iter__(self): - count = ctypes.c_ulonglong(0) - funcs = core.BNGetAnalysisFunctionList(self.handle, count) - try: - for i in range(0, count.value): - yield binaryninja.function.Function(self, core.BNNewFunctionReference(funcs[i])) - finally: - core.BNFreeFunctionList(funcs, count.value) - @property def parent_view(self): """View that contains the raw data used by this view (read-only)""" @@ -1909,81 +2003,6 @@ class BinaryView(object): def new_auto_function_analysis_suppressed(self, suppress): core.BNSetNewAutoFunctionAnalysisSuppressed(self.handle, suppress) - def __len__(self): - return int(core.BNGetViewLength(self.handle)) - - def __getitem__(self, i): - if isinstance(i, tuple): - result = bytes() - for s in i: - result += self.__getitem__(s) - return result - elif isinstance(i, slice): - if i.step is not None: - raise IndexError("step not implemented") - i = i.indices(self.end) - start = i[0] - stop = i[1] - if stop <= start: - return "" - return self.read(start, stop - start) - elif i < 0: - if i >= -len(self): - value = self.read(int(len(self) + i), 1) - if len(value) == 0: - return IndexError("index not readable") - return value - raise IndexError("index out of range") - elif (i >= self.start) and (i < self.end): - value = self.read(int(i), 1) - if len(value) == 0: - return IndexError("index not readable") - return value - else: - raise IndexError("index out of range") - - def __setitem__(self, i, value): - if isinstance(i, slice): - if i.step is not None: - raise IndexError("step not supported on assignment") - i = i.indices(self.end) - start = i[0] - stop = i[1] - if stop < start: - stop = start - if len(value) != (stop - start): - self.remove(start, stop - start) - self.insert(start, value) - else: - self.write(start, value) - elif i < 0: - if i >= -len(self): - if len(value) != 1: - raise ValueError("expected single byte for assignment") - if self.write(int(len(self) + i), value) != 1: - raise IndexError("index not writable") - else: - raise IndexError("index out of range") - elif (i >= self.start) and (i < self.end): - if len(value) != 1: - raise ValueError("expected single byte for assignment") - if self.write(int(i), value) != 1: - raise IndexError("index not writable") - else: - raise IndexError("index out of range") - - def __repr__(self): - start = self.start - length = len(self) - if start != 0: - size = "start %#x, len %#x" % (start, length) - else: - size = "len %#x" % length - filename = self._file.filename - if len(filename) > 0: - return "" % (filename, size) - return "" % (size) - def _init(self, ctxt): try: return self.init() @@ -5386,15 +5405,18 @@ class BinaryReader(object): def __del__(self): core.BNFreeBinaryReader(self.handle) - def __eq__(self, value): - if not isinstance(value, BinaryReader): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents) - def __ne__(self, value): - if not isinstance(value, BinaryReader): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.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.handle.contents)) @property def endianness(self): @@ -5706,15 +5728,18 @@ class BinaryWriter(object): def __del__(self): core.BNFreeBinaryWriter(self.handle) - def __eq__(self, value): - if not isinstance(value, BinaryWriter): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents) - def __ne__(self, value): - if not isinstance(value, BinaryWriter): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.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.handle.contents)) @property def endianness(self): @@ -5920,6 +5945,27 @@ class StructuredDataValue(object): self._address = address self._value = value + def __str__(self): + decode_str = "{}B".format(self._type.width) + return ' '.join(["{:02x}".format(x) for x in struct.unpack(decode_str, self._value)]) + + def __repr__(self): + return "".format(str(self._type), str(self)) + + def __int__(self): + if self._type.width == 1: + code = "B" + elif self._type.width == 2: + code = "H" + elif self._type.width == 4: + code = "I" + elif self._type.width == 8: + code = "Q" + else: + raise Exception("Could not convert to integer with width {}".format(self._type.width)) + + return struct.unpack(code, self._value)[0] + @property def type(self): return self._type @@ -5944,27 +5990,6 @@ class StructuredDataValue(object): def str(self): return str(self) - def __int__(self): - if self._type.width == 1: - code = "B" - elif self._type.width == 2: - code = "H" - elif self._type.width == 4: - code = "I" - elif self._type.width == 8: - code = "Q" - else: - raise Exception("Could not convert to integer with width {}".format(self._type.width)) - - return struct.unpack(code, self._value)[0] - - def __str__(self): - decode_str = "{}B".format(self._type.width) - return ' '.join(["{:02x}".format(x) for x in struct.unpack(decode_str, self._value)]) - - def __repr__(self): - return "".format(str(self._type), str(self)) - class StructuredDataView(object): """ @@ -6000,19 +6025,12 @@ class StructuredDataView(object): self._lookup_structure() self._define_members() - def _lookup_structure(self): - s = self._bv.get_type_by_name(self._structure_name) - if s is None: - raise Exception("Could not find structure with name: {}".format(self._structure_name)) - - if s.type_class != TypeClass.StructureTypeClass: - raise Exception("{} is not a StructureTypeClass, got: {}".format(self._structure_name, s._type_class)) - - self._structure = s.structure + def __repr__(self): + return "".format(self._structure_name, + self._structure.width, self._address) - def _define_members(self): - for m in self._structure.members: - self._members[m.name] = m + def __len__(self): + return self._structure.width def __getattr__(self, key): m = self._members.get(key, None) @@ -6056,9 +6074,16 @@ class StructuredDataView(object): return rv - def __repr__(self): - return "".format(self._structure_name, - self._structure.width, self._address) + def _lookup_structure(self): + s = self._bv.get_type_by_name(self._structure_name) + if s is None: + raise Exception("Could not find structure with name: {}".format(self._structure_name)) - def __len__(self): - return self._structure.width + if s.type_class != TypeClass.StructureTypeClass: + raise Exception("{} is not a StructureTypeClass, got: {}".format(self._structure_name, s._type_class)) + + self._structure = s.structure + + def _define_members(self): + for m in self._structure.members: + self._members[m.name] = m diff --git a/python/callingconvention.py b/python/callingconvention.py index c6e5895a..66569a96 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -159,15 +159,24 @@ class CallingConvention(object): if self.handle is not None: core.BNFreeCallingConvention(self.handle) - def __eq__(self, value): - if not isinstance(value, CallingConvention): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + def __repr__(self): + return "" % (self.arch.name, self.name) + + def __str__(self): + return self.name + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents) - def __ne__(self, value): - if not isinstance(value, CallingConvention): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.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.handle.contents)) def _get_caller_saved_regs(self, ctxt, count): try: @@ -364,12 +373,6 @@ class CallingConvention(object): result[0].index = in_var[0].index result[0].storage = in_var[0].storage - def __repr__(self): - return "" % (self.arch.name, self.name) - - def __str__(self): - return self.name - def perform_get_incoming_reg_value(self, reg, func): reg_stack = self.arch.get_reg_stack_for_reg(reg) if reg_stack is not None: diff --git a/python/filemetadata.py b/python/filemetadata.py index ce88fdce..58afeeec 100644 --- a/python/filemetadata.py +++ b/python/filemetadata.py @@ -88,6 +88,27 @@ class FileMetadata(object): core.BNSetFilename(self.handle, str(filename)) self._nav = None + def __repr__(self): + return "" % self.filename + + def __del__(self): + if self.navigation is not None: + core.BNSetFileMetadataNavigationHandler(self.handle, None) + core.BNFreeFileMetadata(self.handle) + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.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.handle.contents)) + @property def nav(self): """ @@ -98,21 +119,6 @@ class FileMetadata(object): def nav(self, value): self._nav = value - def __del__(self): - if self.navigation is not None: - core.BNSetFileMetadataNavigationHandler(self.handle, None) - core.BNFreeFileMetadata(self.handle) - - def __eq__(self, value): - if not isinstance(value, FileMetadata): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) - - def __ne__(self, value): - if not isinstance(value, FileMetadata): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) - @classmethod def _unregister(cls, f): handle = ctypes.cast(f, ctypes.c_void_p) @@ -373,9 +379,3 @@ class FileMetadata(object): if view is None: return None return binaryninja.binaryview.BinaryView(file_metadata = self, handle = view) - - def __setattr__(self, name, value): - try: - object.__setattr__(self, name, value) - except AttributeError: - raise AttributeError("attribute '%s' is read only" % name) diff --git a/python/flowgraph.py b/python/flowgraph.py index 6c3f41f7..404aa4bb 100644 --- a/python/flowgraph.py +++ b/python/flowgraph.py @@ -67,15 +67,41 @@ class FlowGraphNode(object): if self.handle is not None: core.BNFreeFlowGraphNode(self.handle) - def __eq__(self, value): - if not isinstance(value, FlowGraphNode): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + def __repr__(self): + block = self.basic_block + if block: + arch = block.arch + if arch: + return "" % (arch.name, block.start, block.end) + else: + return "" % (block.start, block.end) + return "" - def __ne__(self, value): - if not isinstance(value, FlowGraphNode): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __iter__(self): + count = ctypes.c_ulonglong() + lines = core.BNGetFlowGraphNodeLines(self.handle, count) + block = self.basic_block + try: + for i in range(0, count.value): + addr = lines[i].addr + if (lines[i].instrIndex != 0xffffffffffffffff) and (block is not None) and hasattr(block, 'il_function'): + il_instr = block.il_function[lines[i].instrIndex] + else: + il_instr = None + tokens = function.InstructionTextToken.get_instruction_lines(lines[i].tokens, lines[i].count) + yield function.DisassemblyTextLine(tokens, addr, il_instr) + finally: + core.BNFreeDisassemblyTextLines(lines, count.value) @property def graph(self): @@ -245,32 +271,6 @@ class FlowGraphNode(object): color = highlight.HighlightColor(color) core.BNSetFlowGraphNodeHighlight(self.handle, color._get_core_struct()) - def __repr__(self): - block = self.basic_block - if block: - arch = block.arch - if arch: - return "" % (arch.name, block.start, block.end) - else: - return "" % (block.start, block.end) - return "" - - def __iter__(self): - count = ctypes.c_ulonglong() - lines = core.BNGetFlowGraphNodeLines(self.handle, count) - block = self.basic_block - try: - for i in range(0, count.value): - addr = lines[i].addr - if (lines[i].instrIndex != 0xffffffffffffffff) and (block is not None) and hasattr(block, 'il_function'): - il_instr = block.il_function[lines[i].instrIndex] - else: - il_instr = None - tokens = function.InstructionTextToken.get_instruction_lines(lines[i].tokens, lines[i].count) - yield function.DisassemblyTextLine(tokens, addr, il_instr) - finally: - core.BNFreeDisassemblyTextLines(lines, count.value) - def add_outgoing_edge(self, edge_type, target): """ ``add_outgoing_edge`` connects two flow graph nodes with an edge. @@ -366,15 +366,42 @@ class FlowGraph(object): def __del__(self): core.BNFreeFlowGraph(self.handle) - def __eq__(self, value): - if not isinstance(value, FlowGraph): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + def __repr__(self): + function = self.function + if function is None: + return "" + return "" % repr(function) + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) - def __ne__(self, value): - if not isinstance(value, FlowGraph): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + def __setattr__(self, name, value): + try: + object.__setattr__(self, name, value) + except AttributeError: + raise AttributeError("attribute '%s' is read only" % name) + + def __iter__(self): + count = ctypes.c_ulonglong() + nodes = core.BNGetFlowGraphNodes(self.handle, count) + try: + for i in range(0, count.value): + yield FlowGraphNode(self, core.BNNewFlowGraphNodeReference(nodes[i])) + finally: + core.BNFreeFlowGraphNodeList(nodes, count.value) + + def __getitem__(self, i): + node = core.BNGetFlowGraphNode(self.handle, i) + if node is None: + return None + return FlowGraphNode(self, node) def _prepare_for_layout(self, ctxt): try: @@ -639,27 +666,6 @@ class FlowGraph(object): def shows_secondary_reg_highlighting(self, value): self.set_option(FlowGraphOption.FlowGraphShowsSecondaryRegisterHighlighting, value) - def __setattr__(self, name, value): - try: - object.__setattr__(self, name, value) - except AttributeError: - raise AttributeError("attribute '%s' is read only" % name) - - def __repr__(self): - function = self.function - if function is None: - return "" - return "" % repr(function) - - def __iter__(self): - count = ctypes.c_ulonglong() - nodes = core.BNGetFlowGraphNodes(self.handle, count) - try: - for i in range(0, count.value): - yield FlowGraphNode(self, core.BNNewFlowGraphNodeReference(nodes[i])) - finally: - core.BNFreeFlowGraphNodeList(nodes, count.value) - def layout(self, callback = None): """ ``layout`` starts rendering a graph for display. Once a layout is complete, each node will contain @@ -712,12 +718,6 @@ class FlowGraph(object): """ return core.BNAddFlowGraphNode(self.handle, node.handle) - def __getitem__(self, i): - node = core.BNGetFlowGraphNode(self.handle, i) - if node is None: - return None - return FlowGraphNode(self, node) - def show(self, title): """ ``show`` displays the graph in a new tab in the UI. diff --git a/python/function.py b/python/function.py index 81cfc6b6..7f9648f5 100644 --- a/python/function.py +++ b/python/function.py @@ -49,6 +49,19 @@ class LookupTableEntry(object): def __repr__(self): return "[%s] -> %#x" % (', '.join(["%#x" % i for i in self.from_values]), self.to_value) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return (self._from_values, self._to_value) == (other._from_values, other._to_value) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash((self._from_values, self._to_value)) + @property def from_values(self): """ """ @@ -113,26 +126,30 @@ class RegisterValue(object): return "" def __hash__(self): - if self._type in [RegisterValueType.ConstantValue, RegisterValueType.ConstantPointerValue, RegisterValueType.ImportedAddressValue, RegisterValueType.ReturnAddressValue]: - return hash(self._value) - elif self.type == RegisterValueType.EntryValue: - return hash(self._reg) - elif self._type == RegisterValueType.StackFrameOffset: - return hash(self._offset) + if self._type in [RegisterValueType.ConstantValue, RegisterValueType.ConstantPointerValue, RegisterValueType.ImportedAddressValue, RegisterValueType.ReturnAddressValue]: + return hash(self._value) + elif self.type == RegisterValueType.EntryValue: + return hash(self._reg) + elif self._type == RegisterValueType.StackFrameOffset: + return hash(self._offset) def __eq__(self, other): - if self._type in [RegisterValueType.ConstantValue, RegisterValueType.ConstantPointerValue, RegisterValueType.ImportedAddressValue, RegisterValueType.ReturnAddressValue] and isinstance(other, numbers.Integral): - return self._value == other - elif self._type in [RegisterValueType.ConstantValue, RegisterValueType.ConstantPointerValue, RegisterValueType.ImportedAddressValue, RegisterValueType.ReturnAddressValue] and hasattr(other, 'type') and other.type == self._type: - return self._value == other.value - elif self._type == RegisterValueType.EntryValue and hasattr(other, "type") and other.type == self._type: - return self._reg == other.reg - elif self._type == RegisterValueType.StackFrameOffset and hasattr(other, 'type') and other.type == self._type: - return self._offset == other.offset - elif self._type == RegisterValueType.StackFrameOffset and isinstance(other, numbers.Integral): - return self._offset == other - else: - raise TypeError("'%s' is not valid for comparison to '%s'" % (other, self)) + if self._type in [RegisterValueType.ConstantValue, RegisterValueType.ConstantPointerValue, RegisterValueType.ImportedAddressValue, RegisterValueType.ReturnAddressValue] and isinstance(other, numbers.Integral): + return self._value == other + elif self._type in [RegisterValueType.ConstantValue, RegisterValueType.ConstantPointerValue, RegisterValueType.ImportedAddressValue, RegisterValueType.ReturnAddressValue] and hasattr(other, 'type') and other.type == self._type: + return self._value == other.value + elif self._type == RegisterValueType.EntryValue and hasattr(other, "type") and other.type == self._type: + return self._reg == other.reg + elif self._type == RegisterValueType.StackFrameOffset and hasattr(other, 'type') and other.type == self._type: + return self._offset == other.offset + elif self._type == RegisterValueType.StackFrameOffset and isinstance(other, numbers.Integral): + return self._offset == other + return NotImplemented + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) def _to_api_object(self): result = core.BNRegisterValue() @@ -351,6 +368,19 @@ class PossibleValueSet(object): return "" return "" + def __eq__(self, other): + if self.type in [RegisterValueType.ConstantValue, RegisterValueType.ConstantValue] and isinstance(other, numbers.Integral): + return self.value == other + if self.type in [RegisterValueType.ConstantValue, RegisterValueType.ConstantValue] and hasattr(other, 'type') and other.type == self.type: + return self.value == other.value + else: + return self == other + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + @property def type(self): """ """ @@ -431,14 +461,6 @@ class PossibleValueSet(object): """ """ self._values = value - def __eq__(self, other): - if self.type in [RegisterValueType.ConstantValue, RegisterValueType.ConstantValue] and isinstance(other, numbers.Integral): - return self.value == other - if self.type in [RegisterValueType.ConstantValue, RegisterValueType.ConstantValue] and hasattr(other, 'type') and other.type == self.type: - return self.value == other.value - else: - return self == other - class StackVariableReference(object): def __init__(self, src_operand, t, name, var, ref_ofs, size): @@ -460,6 +482,20 @@ class StackVariableReference(object): return "" % (self._source_operand, self._name, self._var.storage) return "" % (self._source_operand, self._name) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return (self._source_operand, self._type, self._name, self._var, self._referenced_offset, self._size) == \ + (other._source_operand, other._type, other._name, other._var, other._referenced_offset, other._size) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash((self._source_operand, self._type, self._name, self._var, self._referenced_offset, self._size)) + @property def source_operand(self): """ """ @@ -541,6 +577,27 @@ class Variable(object): self._name = name self._type = var_type + def __repr__(self): + if self._type is None: + return "" % self.name + return "" % (self._type.get_string_before_name(), self.name, self._type.get_string_after_name()) + + def __str__(self): + return self.name + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return (self.identifier, self.function) == (other.identifier, other.function) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash((self.identifier, self.function)) + @property def function(self): """Function where the variable is defined""" @@ -609,23 +666,6 @@ class Variable(object): var = core.BNFromVariableIdentifier(identifier) return Variable(func, VariableSourceType(var.type), var.index, var.storage, name, var_type) - def __repr__(self): - if self._type is None: - return "" % self.name - return "" % (self._type.get_string_before_name(), self.name, self._type.get_string_after_name()) - - def __str__(self): - return self.name - - def __eq__(self, other): - if not isinstance(other, Variable): - return False - return (self.identifier, self.function) == (other.identifier, other.function) - - def __hash__(self): - return hash((self.identifier, self.function)) - - class ConstantReference(object): def __init__(self, val, size, ptr, intermediate): self._value = val @@ -698,6 +738,9 @@ class ParameterVariables(object): def __repr__(self): return repr(self._vars) + def __len__(self): + return len(self._vars) + def __iter__(self): for var in self._vars: yield var @@ -705,9 +748,6 @@ class ParameterVariables(object): def __getitem__(self, idx): return self._vars[idx] - def __len__(self): - return len(self._vars) - def with_confidence(self, confidence): return ParameterVariables(list(self._vars), confidence = confidence) @@ -756,20 +796,42 @@ class Function(object): core.BNReleaseAdvancedFunctionAnalysisDataMultiple(self.handle, self._advanced_analysis_requests) core.BNFreeFunction(self.handle) - def __lt__(self, value): - if not isinstance(value, Function): - raise TypeError("Can only compare to other Function objects") - return self.start < value.start - - def __eq__(self, value): - if not isinstance(value, Function): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + def __repr__(self): + arch = self.arch + if arch: + return "" % (arch.name, self.start) + else: + return "" % self.start - def __ne__(self, value): - if not isinstance(value, Function): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __lt__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.start < other.start + + def __gt__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.start > other.start + + def __le__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.start <= other.start + + def __ge__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.start >= other.start def __hash__(self): return hash((self.start, self.arch.name, self.platform.name)) @@ -798,25 +860,12 @@ class Function(object): finally: core.BNFreeBasicBlockList(blocks, count.value) - def __setattr__(self, name, value): - try: - object.__setattr__(self, name, value) - except AttributeError: - raise AttributeError("attribute '%s' is read only" % name) - def __str__(self): result = "" for token in self.type_tokens: result += token.text return result - def __repr__(self): - arch = self.arch - if arch: - return "" % (arch.name, self.start) - else: - return "" % self.start - @classmethod def _unregister(cls, func): handle = ctypes.cast(func, ctypes.c_void_p) diff --git a/python/highlevelil.py b/python/highlevelil.py index 5cf94b34..1e680274 100644 --- a/python/highlevelil.py +++ b/python/highlevelil.py @@ -48,10 +48,17 @@ class HighLevelILOperationAndSize(object): def __eq__(self, other): if isinstance(other, HighLevelILOperation): return other == self._operation - if isinstance(other, HighLevelILOperationAndSize): + if isinstance(other, self.__class__): return other.size == self._size and other.operation == self._operation - else: - return False + return NotImplemented + + def __ne__(self, other): + if isinstance(other, self.__class__) or isinstance(other, HighLevelILOperation): + return not (self == other) + return NotImplemented + + def __hash__(self): + return hash((self._operation, self._size)) @property def operation(self): @@ -77,6 +84,12 @@ class GotoLabel(object): self._function = function self._id = id + def __repr__(self): + return "" % self.name + + def __str__(self): + return self.name + @property def label_id(self): return self._id @@ -97,12 +110,6 @@ class GotoLabel(object): def uses(self): return self._function.get_label_uses(self._id) - def __str__(self): - return self.name - - def __repr__(self): - return "" % self.name - class HighLevelILInstruction(object): """ @@ -334,10 +341,18 @@ class HighLevelILInstruction(object): continuation = "..." return "<%s: %s%s>" % (self._operation.name, first_line, continuation) - def __eq__(self, value): - if not isinstance(value, type(self)): - return False - return self._function == value.function and self._expr_index == value.expr_index + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return (self._function, self._expr_index) == (other._function, other._expr_index) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash((self._function, self._expr_index)) @property def lines(self): @@ -380,21 +395,11 @@ class HighLevelILInstruction(object): result.append(HighLevelILOperationAndSize(self._operation, self._size)) return result - def __setattr__(self, name, value): - try: - object.__setattr__(self, name, value) - except AttributeError: - raise AttributeError("attribute '%s' is read only" % name) - @property def function(self): """ """ return self._function - @function.setter - def function(self, value): - self._function = value - @property def expr_index(self): """ """ @@ -479,16 +484,6 @@ class HighLevelILInstruction(object): return None return HighLevelILInstruction(self._function, self._parent, self._as_ast) - @property - def instr_index(self): - """ """ - return self._instr_index - - @property - def instr(self): - """High level IL instruction that contains this expression""" - return self._function[self._instr_index] - @property def ssa_form(self): """SSA form of expression (read-only)""" @@ -608,22 +603,22 @@ class HighLevelILFunction(object): func_handle = self._source_function.handle self.handle = core.BNCreateHighLevelILFunction(arch.handle, func_handle) - def __hash__(self): - return hash(('HLIL', self._source_function)) - def __del__(self): if self.handle is not None: core.BNFreeHighLevelILFunction(self.handle) - def __eq__(self, value): - if not isinstance(value, HighLevelILFunction): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents) - def __ne__(self, value): - if not isinstance(value, HighLevelILFunction): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash(('HLIL', self._source_function)) @property def current_address(self): diff --git a/python/lineardisassembly.py b/python/lineardisassembly.py index 3e49f5ee..44f0aeb9 100644 --- a/python/lineardisassembly.py +++ b/python/lineardisassembly.py @@ -35,12 +35,12 @@ class LinearDisassemblyLine(object): self.block = block self.contents = contents - def __str__(self): - return str(self.contents) - def __repr__(self): return repr(self.contents) + def __str__(self): + return str(self.contents) + class LinearViewObjectIdentifier(object): def __init__(self, name, start = None, end = None): @@ -48,29 +48,8 @@ class LinearViewObjectIdentifier(object): self._start = start self._end = end - @property - def name(self): - return self._name - - @property - def address(self): - return self._start - - @property - def start(self): - return self._start - - @property - def end(self): - return self._end - - @property - def has_address(self): - return self._start is not None - - @property - def has_range(self): - return self._start is not None and self._end is not None + def __repr__(self): + return "" def __str__(self): if not self.has_address: @@ -79,8 +58,18 @@ class LinearViewObjectIdentifier(object): return "%s 0x%x-0x%x" % (self._name, self._start, self._end) return "%s 0x%x" % (self._name, self._start) - def __repr__(self): - return "" + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return (self._name, self._start, self._end) == (other._name, other._start, other._end) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash((self._name, self._start, self._end)) def _to_api_object(self, obj = None): if obj is None: @@ -102,6 +91,30 @@ class LinearViewObjectIdentifier(object): result.end = 0 return result + @property + def name(self): + return self._name + + @property + def address(self): + return self._start + + @property + def start(self): + return self._start + + @property + def end(self): + return self._end + + @property + def has_address(self): + return self._start is not None + + @property + def has_range(self): + return self._start is not None and self._end is not None + @classmethod def _from_api_object(cls, obj): if obj.type == LinearViewObjectIdentifierType.AddressLinearViewObject: @@ -121,6 +134,18 @@ class LinearViewObject(object): def __del__(self): core.BNFreeLinearViewObject(self.handle) + def __repr__(self): + return "" + + def __len__(self): + return self.end - self.start + + def __str__(self): + result = str(self.identifier) + if self._parent is not None: + result = str(self._parent) + "/" + result + return result + @property def first_child(self): result = core.BNGetFirstLinearViewObjectChild(self.handle) @@ -189,18 +214,6 @@ class LinearViewObject(object): def ordering_index_total(self): return core.BNGetLinearViewObjectOrderingIndexTotal(self.handle) - def __len__(self): - return self.end - self.start - - def __str__(self): - result = str(self.identifier) - if self._parent is not None: - result = str(self._parent) + "/" + result - return result - - def __repr__(self): - return "" - def child_for_address(self, addr): result = core.BNGetLinearViewObjectChildForAddress(self.handle, addr) if not result: @@ -323,6 +336,47 @@ class LinearViewCursor(object): def __del__(self): core.BNFreeLinearViewCursor(self.handle) + def __repr__(self): + return "" + + def __str__(self): + return str(self.current_object) + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return LinearViewCursor.compare(self, other) == 0 + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return LinearViewCursor.compare(self, other) != 0 + + def __lt__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return LinearViewCursor.compare(self, other) < 0 + + def __le__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return LinearViewCursor.compare(self, other) <= 0 + + def __gt__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return LinearViewCursor.compare(self, other) > 0 + + def __ge__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return LinearViewCursor.compare(self, other) >= 0 + + def __cmp__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return LinearViewCursor.compare(self, other) + @property def before_begin(self): return core.BNIsLinearViewCursorBeforeBegin(self.handle) @@ -431,47 +485,6 @@ class LinearViewCursor(object): def duplicate(self): return LinearViewCursor(None, handle = core.BNDuplicateLinearViewCursor(self.handle)) - def __str__(self): - return str(self.current_object) - - def __repr__(self): - return "" - - def __eq__(self, other): - if isinstance(other, LinearViewCursor): - return LinearViewCursor.compare(self, other) == 0 - return False - - def __ne__(self, other): - if isinstance(other, LinearViewCursor): - return LinearViewCursor.compare(self, other) != 0 - return True - - def __lt__(self, other): - if isinstance(other, LinearViewCursor): - return LinearViewCursor.compare(self, other) < 0 - return False - - def __le__(self, other): - if isinstance(other, LinearViewCursor): - return LinearViewCursor.compare(self, other) <= 0 - return False - - def __gt__(self, other): - if isinstance(other, LinearViewCursor): - return LinearViewCursor.compare(self, other) > 0 - return False - - def __ge__(self, other): - if isinstance(other, LinearViewCursor): - return LinearViewCursor.compare(self, other) >= 0 - return False - - def __cmp__(self, other): - if isinstance(other, LinearViewCursor): - return LinearViewCursor.compare(self, other) - return 0 - @classmethod def compare(cls, a, b): return core.BNCompareLinearViewCursors(a.handle, b.handle) diff --git a/python/lowlevelil.py b/python/lowlevelil.py index ca00f769..17536beb 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -54,16 +54,24 @@ class ILRegister(object): def info(self): return self._arch.regs[self._name] - def __str__(self): + def __repr__(self): return self._name - def __repr__(self): + def __str__(self): return self._name def __eq__(self, other): - if not isinstance(other, type(self)): - return False - return self.info == other.info + if not isinstance(other, self.__class__): + return NotImplemented + return (self._arch, self._index, self._name) == (other._arch, other._index, other._name) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash((self._arch, self._index, self._name)) @property def arch(self): @@ -112,16 +120,24 @@ class ILRegisterStack(object): def info(self): return self._arch.reg_stacks[self._name] - def __str__(self): + def __repr__(self): return self._name - def __repr__(self): + def __str__(self): return self._name def __eq__(self, other): - if not isinstance(other, type(self)): - return False - return self.info == other.info + if not isinstance(other, self.__class__): + return NotImplemented + return (self._arch, self._index, self._name) == (other._arch, other._index, other._name) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash((self._arch, self._index, self._name)) @property def arch(self): @@ -161,12 +177,25 @@ class ILFlag(object): else: self._name = self._arch.get_flag_name(self._index) - def __str__(self): + def __repr__(self): return self._name - def __repr__(self): + def __str__(self): return self._name + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return (self._arch, self._index, self._name) == (other._arch, other._index, other._name) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash((self._arch, self._index, self._name)) + @property def arch(self): """ """ @@ -210,16 +239,24 @@ class ILSemanticFlagClass(object): self._index = sem_class self._name = self._arch.get_semantic_flag_class_name(self._index) - def __str__(self): + def __repr__(self): return self._name - def __repr__(self): + def __str__(self): return self._name def __eq__(self, other): - if not isinstance(other, type(self)): - return False - return self._index == other._index + if not isinstance(other, self.__class__): + return NotImplemented + return (self._arch, self._index, self._name) == (other._arch, other._index, other._name) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash((self._arch, self._index, self._name)) @property def arch(self): @@ -255,16 +292,24 @@ class ILSemanticFlagGroup(object): self._index = sem_group self._name = self._arch.get_semantic_flag_group_name(self._index) - def __str__(self): + def __repr__(self): return self._name - def __repr__(self): + def __str__(self): return self._name def __eq__(self, other): - if not isinstance(other, type(self)): - return False - return self._index == other.index + if not isinstance(other, self.__class__): + return NotImplemented + return (self._arch, self._index, self._name) == (other._arch, other._index, other._name) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash((self._arch, self._index, self._name)) @property def arch(self): @@ -303,16 +348,24 @@ class ILIntrinsic(object): self._inputs = self._arch.intrinsics[self._name].inputs self._outputs = self._arch.intrinsics[self._name].outputs - def __str__(self): + def __repr__(self): return self._name - def __repr__(self): + def __str__(self): return self._name def __eq__(self, other): - if not isinstance(other, type(self)): - return False - return self._index == other.index + if not isinstance(other, self.__class__): + return NotImplemented + return (self._arch, self._index, self._name) == (other._arch, other._index, other._name) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash((self._arch, self._index, self._name)) @property def arch(self): @@ -368,6 +421,19 @@ class SSARegister(object): def __repr__(self): return "" % (repr(self._reg), self._version) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return (self._reg, self._version) == (other._reg, other._version) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash((self._reg, self._version)) + @property def reg(self): """ """ @@ -395,6 +461,19 @@ class SSARegisterStack(object): def __repr__(self): return "" % (repr(self._reg_stack), self._version) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return (self._reg_stack, self._version) == (other._reg_stack, other._version) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash((self._reg_stack, self._version)) + @property def reg_stack(self): """ """ @@ -422,6 +501,19 @@ class SSAFlag(object): def __repr__(self): return "" % (repr(self._flag), self._version) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return (self._flag, self._version) == (other._flag, other._version) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash((self._flag, self._version)) + @property def flag(self): """ """ @@ -449,6 +541,19 @@ class SSARegisterOrFlag(object): def __repr__(self): return "" % (repr(self._reg_or_flag), self._version) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return (self._reg_or_flag == other._reg_or_flag) and (self._version == other._version) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash((self._reg_or_flag, self._version)) + @property def reg_or_flag(self): """ """ @@ -478,6 +583,19 @@ class LowLevelILOperationAndSize(object): return "<%s>" % self._operation.name return "<%s %d>" % (self._operation.name, self._size) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return (self._operation, self._size) == (other._operation, other._size) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __hash__(self): + return hash((self._operation, self._size)) + @property def operation(self): """ """ @@ -811,30 +929,38 @@ class LowLevelILInstruction(object): def __repr__(self): return "" % str(self) - def __eq__(self, value): - if not isinstance(value, type(self)): - return False - return self._function == value.function and self.expr_index == value.expr_index - - def __lt__(self, value): - if not isinstance(value, type(self)): - return False - return self._function == value.function and self.expr_index < value.expr_index - - def __le__(self, value): - if not isinstance(value, type(self)): - return False - return self._function == value.function and self.expr_index <= value.expr_index - - def __gt__(self, value): - if not isinstance(value, type(self)): - return False - return self._function == value.function and self.expr_index > value.expr_index + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self._function == other.function and self.expr_index == other.expr_index + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __lt__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self._function == other.function and self.expr_index < other.expr_index + + def __le__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self._function == other.function and self.expr_index <= other.expr_index + + def __gt__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self._function == other.function and self.expr_index > other.expr_index + + def __ge__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self._function == other.function and self.expr_index >= other.expr_index - def __ge__(self, value): - if not isinstance(value, type(self)): - return False - return self._function == value.function and self.expr_index >= value.expr_index + def __hash__(self): + return hash((self._function, self.expr_index)) @property def tokens(self): @@ -1058,12 +1184,6 @@ class LowLevelILInstruction(object): core.BNFreePossibleValueSet(value) return result - def __setattr__(self, name, value): - try: - object.__setattr__(self, name, value) - except AttributeError: - raise AttributeError("attribute '%s' is read only" % name) - @property def function(self): """ """ @@ -1180,23 +1300,10 @@ class LowLevelILFunction(object): func_handle = self._source_function.handle self.handle = core.BNCreateLowLevelILFunction(arch.handle, func_handle) - def __hash__(self): - return hash(('LLIL', self._source_function)) - def __del__(self): if self.handle is not None: core.BNFreeLowLevelILFunction(self.handle) - def __eq__(self, value): - if not isinstance(value, type(self)): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) - - def __ne__(self, value): - if not isinstance(value, LowLevelILFunction): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) - def __repr__(self): arch = self.source_function.arch if arch: @@ -1204,6 +1311,51 @@ class LowLevelILFunction(object): else: return "" % self.source_function.start + def __len__(self): + return int(core.BNGetLowLevelILInstructionCount(self.handle)) + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.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(('LLIL', self._source_function)) + + def __getitem__(self, i): + if isinstance(i, slice) or isinstance(i, tuple): + raise IndexError("expected integer instruction index") + if isinstance(i, LowLevelILExpr): + return LowLevelILInstruction(self, i.index) + # for backwards compatibility + if isinstance(i, LowLevelILInstruction): + return i + if i < -len(self) or i >= len(self): + raise IndexError("index out of range") + if i < 0: + i = len(self) + i + return LowLevelILInstruction(self, core.BNGetLowLevelILIndexForInstruction(self.handle, i), i) + + def __setitem__(self, i, j): + raise IndexError("instruction modification not implemented") + + def __iter__(self): + count = ctypes.c_ulonglong() + blocks = core.BNGetLowLevelILBasicBlockList(self.handle, count) + view = None + if self._source_function is not None: + view = self._source_function.view + try: + for i in range(0, count.value): + yield LowLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self) + finally: + core.BNFreeBasicBlockList(blocks, count.value) + @property def current_address(self): """Current IL Address (read/write)""" @@ -1294,43 +1446,23 @@ class LowLevelILFunction(object): def mmlil(self): return self.mapped_medium_level_il - def __setattr__(self, name, value): - try: - object.__setattr__(self, name, value) - except AttributeError: - raise AttributeError("attribute '%s' is read only" % name) - - def __len__(self): - return int(core.BNGetLowLevelILInstructionCount(self.handle)) + @property + def arch(self): + """ """ + return self._arch - def __getitem__(self, i): - if isinstance(i, slice) or isinstance(i, tuple): - raise IndexError("expected integer instruction index") - if isinstance(i, LowLevelILExpr): - return LowLevelILInstruction(self, i.index) - # for backwards compatibility - if isinstance(i, LowLevelILInstruction): - return i - if i < -len(self) or i >= len(self): - raise IndexError("index out of range") - if i < 0: - i = len(self) + i - return LowLevelILInstruction(self, core.BNGetLowLevelILIndexForInstruction(self.handle, i), i) + @arch.setter + def arch(self, value): + self._arch = value - def __setitem__(self, i, j): - raise IndexError("instruction modification not implemented") + @property + def source_function(self): + """ """ + return self._source_function - def __iter__(self): - count = ctypes.c_ulonglong() - blocks = core.BNGetLowLevelILBasicBlockList(self.handle, count) - view = None - if self._source_function is not None: - view = self._source_function.view - try: - for i in range(0, count.value): - yield LowLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self) - finally: - core.BNFreeBasicBlockList(blocks, count.value) + @source_function.setter + def source_function(self, value): + self._source_function = value def get_instruction_start(self, addr, arch = None): if arch is None: @@ -2871,30 +3003,27 @@ class LowLevelILFunction(object): settings_obj = None return binaryninja.flowgraph.CoreFlowGraph(core.BNCreateLowLevelILFunctionGraph(self.handle, settings_obj)) - @property - def arch(self): - """ """ - return self._arch - - @arch.setter - def arch(self, value): - self._arch = value - - @property - def source_function(self): - """ """ - return self._source_function - - @source_function.setter - def source_function(self, value): - self._source_function = value - class LowLevelILBasicBlock(basicblock.BasicBlock): def __init__(self, view, handle, owner): super(LowLevelILBasicBlock, self).__init__(handle, view) self._il_function = owner + def __repr__(self): + arch = self.arch + if arch: + return "" % (arch.name, self.start, self.end) + else: + return "" % (self.start, self.end) + + def __hash__(self): + return hash((self.start, self.end, self._il_function)) + + def __contains__(self, instruction): + if type(instruction) != LowLevelILInstruction or instruction.il_basic_block != self: + return False + return True + def __iter__(self): for idx in range(self.start, self.end): yield self._il_function[idx] @@ -2912,21 +3041,6 @@ class LowLevelILBasicBlock(basicblock.BasicBlock): """Internal method by super to instantiate child instances""" return LowLevelILBasicBlock(view, handle, self._il_function) - def __hash__(self): - return hash((self.start, self.end, self._il_function)) - - def __repr__(self): - arch = self.arch - if arch: - return "" % (arch.name, self.start, self.end) - else: - return "" % (self.start, self.end) - - def __contains__(self, instruction): - if type(instruction) != LowLevelILInstruction or instruction.il_basic_block != self: - return False - return True - @property def il_function(self): """ """ diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 21c50817..8b2a4c89 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -43,12 +43,14 @@ class SSAVariable(object): return "" % (repr(self._var), self._version) def __eq__(self, other): - if not isinstance(other, type(self)): - return False - return isinstance(other, SSAVariable) and ( - (self._var, self._version) == - (other.var, other.version) - ) + if not isinstance(other, self.__class__): + return NotImplemented + return (self._var, self._version) == (other.var, other.version) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) def __hash__(self): return hash((self._var, self._version)) @@ -94,13 +96,17 @@ class MediumLevelILOperationAndSize(object): def __eq__(self, other): if isinstance(other, MediumLevelILOperation): return other == self._operation - if isinstance(other, MediumLevelILOperationAndSize): - return other.size == self._size and other.operation == self._operation - else: - return False + if isinstance(other, self.__class__): + return (other.size, other.operation) == (self._size, self._operation) + return NotImplemented + + def __ne__(self, other): + if isinstance(other, MediumLevelILOperation) or isinstance(other, self.__class__): + return not (self == other) + return NotImplemented def __hash__(self): - return hash((self._size, self._operation)) + return hash((self._operation, self._size)) @property def operation(self): @@ -361,34 +367,34 @@ class MediumLevelILInstruction(object): def __repr__(self): return "" % str(self) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self._function == other.function and self._expr_index == other.expr_index + + def __lt__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self._function == other.function and self.expr_index < other.expr_index + + def __le__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self._function == other.function and self.expr_index <= other.expr_index + + def __gt__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self._function == other.function and self.expr_index > other.expr_index + + def __ge__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self._function == other.function and self.expr_index >= other.expr_index + def __hash__(self): return hash((self._instr_index, self._function)) - def __eq__(self, value): - if not isinstance(value, type(self)): - return False - return self._function == value.function and self._expr_index == value.expr_index - - def __lt__(self, value): - if not isinstance(value, type(self)): - return False - return self._function == value.function and self.expr_index < value.expr_index - - def __le__(self, value): - if not isinstance(value, type(self)): - return False - return self._function == value.function and self.expr_index <= value.expr_index - - def __gt__(self, value): - if not isinstance(value, type(self)): - return False - return self._function == value.function and self.expr_index > value.expr_index - - def __ge__(self, value): - if not isinstance(value, type(self)): - return False - return self._function == value.function and self.expr_index >= value.expr_index - @property def tokens(self): """MLIL tokens (read-only)""" @@ -716,12 +722,6 @@ class MediumLevelILInstruction(object): def get_branch_dependence(self, branch_instr): return ILBranchDependence(core.BNGetMediumLevelILBranchDependence(self._function.handle, self._instr_index, branch_instr)) - def __setattr__(self, name, value): - try: - object.__setattr__(self, name, value) - except AttributeError: - raise AttributeError("attribute '%s' is read only" % name) - @property def function(self): """ """ @@ -807,23 +807,10 @@ class MediumLevelILFunction(object): func_handle = self._source_function.handle self.handle = core.BNCreateMediumLevelILFunction(arch.handle, func_handle) - def __hash__(self): - return hash(('MLIL', self._source_function)) - def __del__(self): if self.handle is not None: core.BNFreeMediumLevelILFunction(self.handle) - def __eq__(self, value): - if not isinstance(value, MediumLevelILFunction): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) - - def __ne__(self, value): - if not isinstance(value, MediumLevelILFunction): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) - def __repr__(self): arch = self.source_function.arch if arch: @@ -831,6 +818,51 @@ class MediumLevelILFunction(object): else: return "" % self.source_function.start + def __len__(self): + return int(core.BNGetMediumLevelILInstructionCount(self.handle)) + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.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(('MLIL', self._source_function)) + + def __getitem__(self, i): + if isinstance(i, slice) or isinstance(i, tuple): + raise IndexError("expected integer instruction index") + if isinstance(i, MediumLevelILExpr): + return MediumLevelILInstruction(self, i.index) + # for backwards compatibility + if isinstance(i, MediumLevelILInstruction): + return i + if i < -len(self) or i >= len(self): + raise IndexError("index out of range") + if i < 0: + i = len(self) + i + return MediumLevelILInstruction(self, core.BNGetMediumLevelILIndexForInstruction(self.handle, i), i) + + def __setitem__(self, i, j): + raise IndexError("instruction modification not implemented") + + def __iter__(self): + count = ctypes.c_ulonglong() + blocks = core.BNGetMediumLevelILBasicBlockList(self.handle, count) + view = None + if self._source_function is not None: + view = self._source_function.view + try: + for i in range(0, count.value): + yield MediumLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self) + finally: + core.BNFreeBasicBlockList(blocks, count.value) + @property def current_address(self): """Current IL Address (read/write)""" @@ -895,44 +927,6 @@ class MediumLevelILFunction(object): """Alias for low_level_il""" return self.low_level_il - def __setattr__(self, name, value): - try: - object.__setattr__(self, name, value) - except AttributeError: - raise AttributeError("attribute '%s' is read only" % name) - - def __len__(self): - return int(core.BNGetMediumLevelILInstructionCount(self.handle)) - - def __getitem__(self, i): - if isinstance(i, slice) or isinstance(i, tuple): - raise IndexError("expected integer instruction index") - if isinstance(i, MediumLevelILExpr): - return MediumLevelILInstruction(self, i.index) - # for backwards compatibility - if isinstance(i, MediumLevelILInstruction): - return i - if i < -len(self) or i >= len(self): - raise IndexError("index out of range") - if i < 0: - i = len(self) + i - return MediumLevelILInstruction(self, core.BNGetMediumLevelILIndexForInstruction(self.handle, i), i) - - def __setitem__(self, i, j): - raise IndexError("instruction modification not implemented") - - def __iter__(self): - count = ctypes.c_ulonglong() - blocks = core.BNGetMediumLevelILBasicBlockList(self.handle, count) - view = None - if self._source_function is not None: - view = self._source_function.view - try: - for i in range(0, count.value): - yield MediumLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self) - finally: - core.BNFreeBasicBlockList(blocks, count.value) - def get_instruction_start(self, addr, arch = None): if arch is None: arch = self._arch @@ -1186,6 +1180,13 @@ class MediumLevelILBasicBlock(basicblock.BasicBlock): super(MediumLevelILBasicBlock, self).__init__(handle, view) self.il_function = owner + def __repr__(self): + arch = self.arch + if arch: + return "" % (arch.name, self.start, self.end) + else: + return "" % (self.start, self.end) + def __iter__(self): for idx in range(self.start, self.end): yield self.il_function[idx] @@ -1199,20 +1200,9 @@ class MediumLevelILBasicBlock(basicblock.BasicBlock): else: return self.il_function[self.end + idx] - def _create_instance(self, handle, view): - """Internal method by super to instantiate child instances""" - return MediumLevelILBasicBlock(view, handle, self.il_function) - def __hash__(self): return hash((self.start, self.end, self.il_function)) - def __repr__(self): - arch = self.arch - if arch: - return "" % (arch.name, self.start, self.end) - else: - return "" % (self.start, self.end) - def __contains__(self, instruction): if type(instruction) != MediumLevelILInstruction or instruction.il_basic_block != self: return False @@ -1221,6 +1211,10 @@ class MediumLevelILBasicBlock(basicblock.BasicBlock): else: return False + def _create_instance(self, handle, view): + """Internal method by super to instantiate child instances""" + return MediumLevelILBasicBlock(view, handle, self.il_function) + @property def il_function(self): """ """ diff --git a/python/metadata.py b/python/metadata.py index 27b0abb0..3fe78415 100644 --- a/python/metadata.py +++ b/python/metadata.py @@ -66,85 +66,78 @@ class Metadata(object): else: raise ValueError("{} doesn't contain type of: int, bool, str, float, list, dict".format(type(value).__name__)) - @property - def value(self): - if self.is_integer: - return int(self) - elif self.is_string: - return str(self) - elif self.is_raw: - return bytes(self) - elif self.is_float: - return float(self) - elif self.is_boolean: - return bool(self) - elif self.is_array: - return list(self) - elif self.is_dict: - return self.get_dict() - raise TypeError() - - def get_dict(self): - if not self.is_dict: - raise TypeError() - result = {} - for key in self: - result[key] = self[key] - return result - - @property - def type(self): - return MetadataType(core.BNMetadataGetType(self.handle)) - - @property - def is_integer(self): - return self.is_signed_integer or self.is_unsigned_integer - - @property - def is_signed_integer(self): - return core.BNMetadataIsSignedInteger(self.handle) - - @property - def is_unsigned_integer(self): - return core.BNMetadataIsUnsignedInteger(self.handle) - - @property - def is_float(self): - return core.BNMetadataIsDouble(self.handle) - - @property - def is_boolean(self): - return core.BNMetadataIsBoolean(self.handle) - - @property - def is_string(self): - return core.BNMetadataIsString(self.handle) - - @property - def is_raw(self): - return core.BNMetadataIsRaw(self.handle) - - @property - def is_array(self): - return core.BNMetadataIsArray(self.handle) - - @property - def is_dict(self): - return core.BNMetadataIsKeyValueStore(self.handle) - - def remove(self, key_or_index): - if isinstance(key_or_index, str) and self.is_dict: - core.BNMetadataRemoveKey(self.handle, key_or_index) - elif isinstance(key_or_index, int) and self.is_array: - core.BNMetadataRemoveIndex(self.handle, key_or_index) - else: - raise TypeError("remove only valid for dict and array objects") - def __len__(self): if self.is_array or self.is_dict or self.is_string or self.is_raw: return core.BNMetadataSize(self.handle) raise Exception("Metadata object doesn't support len()") + def __eq__(self, other): + if isinstance(other, int) and self.is_integer: + return int(self) == other + elif isinstance(other, str) and (self.is_string or self.is_raw): + return str(self) == other + elif isinstance(other, float) and self.is_float: + return float(self) == other + elif isinstance(other, bool) and self.is_boolean: + return bool(self) == other + elif self.is_array and ((isinstance(other, Metadata) and other.is_array) or isinstance(other, list)): + if len(self) != len(other): + return False + for a, b in zip(self, other): + if a != b: + return False + return True + elif self.is_dict and ((isinstance(other, Metadata) and other.is_dict) or isinstance(other, dict)): + if len(self) != len(other): + return False + for a, b in zip(self, other): + if a != b or self[a] != other[b]: + return False + return True + elif isinstance(other, Metadata) and self.is_integer and other.is_integer: + return int(self) == int(other) + elif isinstance(other, Metadata) and (self.is_string or self.is_raw) and (other.is_string or other.is_raw): + return str(self) == str(other) + elif isinstance(other, Metadata) and self.is_float and other.is_float: + return float(self) == float(other) + elif isinstance(other, Metadata) and self.is_boolean and other.is_boolean: + return bool(self) == bool(other) + return NotImplemented + + def __ne__(self, other): + if isinstance(other, int) and self.is_integer: + return int(self) != other + elif isinstance(other, str) and (self.is_string or self.is_raw): + return str(self) != other + elif isinstance(other, float) and self.is_float: + return float(self) != other + elif isinstance(other, bool): + return bool(self) != other + elif self.is_array and ((isinstance(other, Metadata) and other.is_array) or isinstance(other, list)): + if len(self) != len(other): + return True + areEqual = True + for a, b in zip(self, other): + if a != b: + areEqual = False + return not areEqual + elif self.is_dict and ((isinstance(other, Metadata) and other.is_dict) or isinstance(other, dict)): + if len(self) != len(other): + return True + for a, b in zip(self, other): + if a != b or self[a] != other[b]: + return True + return False + elif isinstance(other, Metadata) and self.is_integer and other.is_integer: + return int(self) != int(other) + elif isinstance(other, Metadata) and (self.is_string or self.is_raw) and (other.is_string or other.is_raw): + return str(self) != str(other) + elif isinstance(other, Metadata) and self.is_float and other.is_float: + return float(self) != float(other) + elif isinstance(other, Metadata) and self.is_boolean and other.is_boolean: + return bool(self) != bool(other) + return NotImplemented + def __iter__(self): if self.is_array: for i in range(core.BNMetadataSize(self.handle)): @@ -215,68 +208,76 @@ class Metadata(object): raise ValueError("Metadata object is not boolean type") return core.BNMetadataGetBoolean(self.handle) - def __eq__(self, other): - if isinstance(other, int) and self.is_integer: - return int(self) == other - elif isinstance(other, str) and (self.is_string or self.is_raw): - return str(self) == other - elif isinstance(other, float) and self.is_float: - return float(self) == other - elif isinstance(other, bool) and self.is_boolean: - return bool(self) == other - elif self.is_array and ((isinstance(other, Metadata) and other.is_array) or isinstance(other, list)): - if len(self) != len(other): - return False - for a, b in zip(self, other): - if a != b: - return False - return True - elif self.is_dict and ((isinstance(other, Metadata) and other.is_dict) or isinstance(other, dict)): - if len(self) != len(other): - return False - for a, b in zip(self, other): - if a != b or self[a] != other[b]: - return False - return True - elif isinstance(other, Metadata) and self.is_integer and other.is_integer: - return int(self) == int(other) - elif isinstance(other, Metadata) and (self.is_string or self.is_raw) and (other.is_string or other.is_raw): - return str(self) == str(other) - elif isinstance(other, Metadata) and self.is_float and other.is_float: - return float(self) == float(other) - elif isinstance(other, Metadata) and self.is_boolean and other.is_boolean: - return bool(self) == bool(other) - raise NotImplementedError() + @property + def value(self): + if self.is_integer: + return int(self) + elif self.is_string: + return str(self) + elif self.is_raw: + return bytes(self) + elif self.is_float: + return float(self) + elif self.is_boolean: + return bool(self) + elif self.is_array: + return list(self) + elif self.is_dict: + return self.get_dict() + raise TypeError() - def __ne__(self, other): - if isinstance(other, int) and self.is_integer: - return int(self) != other - elif isinstance(other, str) and (self.is_string or self.is_raw): - return str(self) != other - elif isinstance(other, float) and self.is_float: - return float(self) != other - elif isinstance(other, bool): - return bool(self) != other - elif self.is_array and ((isinstance(other, Metadata) and other.is_array) or isinstance(other, list)): - if len(self) != len(other): - return True - areEqual = True - for a, b in zip(self, other): - if a != b: - areEqual = False - return not areEqual - elif self.is_dict and ((isinstance(other, Metadata) and other.is_dict) or isinstance(other, dict)): - if len(self) != len(other): - return True - for a, b in zip(self, other): - if a != b or self[a] != other[b]: - return True - return False - elif isinstance(other, Metadata) and self.is_integer and other.is_integer: - return int(self) != int(other) - elif isinstance(other, Metadata) and (self.is_string or self.is_raw) and (other.is_string or other.is_raw): - return str(self) != str(other) - elif isinstance(other, Metadata) and self.is_float and other.is_float: - return float(self) != float(other) - elif isinstance(other, Metadata) and self.is_boolean and other.is_boolean: - return bool(self) != bool(other) + def get_dict(self): + if not self.is_dict: + raise TypeError() + result = {} + for key in self: + result[key] = self[key] + return result + + @property + def type(self): + return MetadataType(core.BNMetadataGetType(self.handle)) + + @property + def is_integer(self): + return self.is_signed_integer or self.is_unsigned_integer + + @property + def is_signed_integer(self): + return core.BNMetadataIsSignedInteger(self.handle) + + @property + def is_unsigned_integer(self): + return core.BNMetadataIsUnsignedInteger(self.handle) + + @property + def is_float(self): + return core.BNMetadataIsDouble(self.handle) + + @property + def is_boolean(self): + return core.BNMetadataIsBoolean(self.handle) + + @property + def is_string(self): + return core.BNMetadataIsString(self.handle) + + @property + def is_raw(self): + return core.BNMetadataIsRaw(self.handle) + + @property + def is_array(self): + return core.BNMetadataIsArray(self.handle) + + @property + def is_dict(self): + return core.BNMetadataIsKeyValueStore(self.handle) + + def remove(self, key_or_index): + if isinstance(key_or_index, str) and self.is_dict: + core.BNMetadataRemoveKey(self.handle, key_or_index) + elif isinstance(key_or_index, int) and self.is_array: + core.BNMetadataRemoveIndex(self.handle, key_or_index) + else: + raise TypeError("remove only valid for dict and array objects") \ No newline at end of file diff --git a/python/platform.py b/python/platform.py index b4163892..9059e1c4 100644 --- a/python/platform.py +++ b/python/platform.py @@ -32,6 +32,23 @@ from binaryninja import with_metaclass class _PlatformMetaClass(type): + def __iter__(self): + binaryninja._init_plugins() + count = ctypes.c_ulonglong() + platforms = core.BNGetPlatformList(count) + try: + for i in range(0, count.value): + yield Platform(handle = core.BNNewPlatformReference(platforms[i])) + finally: + core.BNFreePlatformList(platforms, count.value) + + def __getitem__(cls, value): + binaryninja._init_plugins() + platform = core.BNGetPlatformByName(str(value)) + if platform is None: + raise KeyError("'%s' is not a valid platform" % str(value)) + return Platform(handle = platform) + @property def list(self): binaryninja._init_plugins() @@ -54,29 +71,6 @@ class _PlatformMetaClass(type): core.BNFreePlatformOSList(platforms, count.value) return result - def __iter__(self): - binaryninja._init_plugins() - count = ctypes.c_ulonglong() - platforms = core.BNGetPlatformList(count) - try: - for i in range(0, count.value): - yield Platform(handle = core.BNNewPlatformReference(platforms[i])) - finally: - core.BNFreePlatformList(platforms, count.value) - - def __setattr__(self, name, value): - try: - type.__setattr__(self, name, value) - except AttributeError: - raise AttributeError("attribute '%s' is read only" % name) - - def __getitem__(cls, value): - binaryninja._init_plugins() - platform = core.BNGetPlatformByName(str(value)) - if platform is None: - raise KeyError("'%s' is not a valid platform" % str(value)) - return Platform(handle = platform) - def get_list(cls, os = None, arch = None): binaryninja._init_plugins() count = ctypes.c_ulonglong() @@ -116,15 +110,21 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): if self.handle is not None: core.BNFreePlatform(self.handle) - def __eq__(self, value): - if not isinstance(value, Platform): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + def __repr__(self): + return "" % self.name - def __ne__(self, value): - if not isinstance(value, Platform): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + def __str__(self): + return self.name + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) @property def list(self): @@ -305,18 +305,6 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): core.BNFreeTypeLibraryList(libs, 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 "" % self.name - - def __str__(self): - return self.name - def register(self, os): """ ``register`` registers the platform for given OS name. diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index 73cb2a0d..af230c75 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -340,9 +340,6 @@ class _ScriptingProviderMetaclass(type): class ScriptingProvider(with_metaclass(_ScriptingProviderMetaclass, object)): - - name = None - instance_class = None _registered_providers = [] def __init__(self, handle = None): @@ -350,12 +347,19 @@ class ScriptingProvider(with_metaclass(_ScriptingProviderMetaclass, object)): self.handle = core.handle_of_type(handle, core.BNScriptingProvider) self.__dict__["name"] = core.BNGetScriptingProviderName(handle) + @property + def name(self): + return NotImplemented + + @property + def instance_class(self): + return NotImplemented + @property def list(self): """Allow tab completion to discover metaclass list property""" pass - def register(self): self._cb = core.BNScriptingProviderCallbacks() self._cb.context = 0 diff --git a/python/settings.py b/python/settings.py index 447604c5..3b92ec5d 100644 --- a/python/settings.py +++ b/python/settings.py @@ -80,15 +80,15 @@ class Settings(object): if self.handle is not Settings.handle and self.handle is not None: core.BNFreeSettings(self.handle) - def __eq__(self, value): - if not isinstance(value, Settings): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) - - def __ne__(self, value): - if not isinstance(value, Settings): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.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((self.instance_id, ctypes.addressof(self.handle.contents))) diff --git a/python/transform.py b/python/transform.py index 946b349b..3e89555d 100644 --- a/python/transform.py +++ b/python/transform.py @@ -166,15 +166,18 @@ class Transform(with_metaclass(_TransformMetaClass, object)): def __repr__(self): return "" % self.name - def __eq__(self, value): - if not isinstance(value, Transform): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents) - def __ne__(self, value): - if not isinstance(value, Transform): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.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.handle.contents)) def _get_parameters(self, ctxt, count): try: diff --git a/python/types.py b/python/types.py index 0d766e5c..b0faf9ed 100644 --- a/python/types.py +++ b/python/types.py @@ -38,7 +38,7 @@ class QualifiedName(object): if isinstance(name, str): self._name = [name] self._byte_name = [name.encode('charmap')] - elif isinstance(name, QualifiedName): + elif isinstance(name, self.__class__): self._name = name.name self._byte_name = [n.encode('charmap') for n in name.name] else: @@ -54,48 +54,57 @@ class QualifiedName(object): def __len__(self): return len(self.name) - def __hash__(self): - return hash(str(self)) - def __eq__(self, other): if isinstance(other, str): return str(self) == other elif isinstance(other, list): return self.name == other - elif isinstance(other, QualifiedName): + elif isinstance(other, self.__class__): return self.name == other.name - return False + return NotImplemented def __ne__(self, other): - return not (self == other) + if isinstance(other, str): + return str(self) != other + elif isinstance(other, list): + return self.name != other + elif isinstance(other, self.__class__): + return self.name != other.name + return NotImplemented def __lt__(self, other): - if isinstance(other, QualifiedName): + if isinstance(other, self.__class__): return self.name < other.name - return False + return NotImplemented def __le__(self, other): - if isinstance(other, QualifiedName): + if isinstance(other, self.__class__): return self.name <= other.name - return False + return NotImplemented def __gt__(self, other): - if isinstance(other, QualifiedName): + if isinstance(other, self.__class__): return self.name > other.name - return False + return NotImplemented def __ge__(self, other): - if isinstance(other, QualifiedName): + if isinstance(other, self.__class__): return self.name >= other.name - return False + return NotImplemented def __cmp__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + if self == other: return 0 if self < other: return -1 return 1 + def __hash__(self): + return hash(str(self)) + def __getitem__(self, key): return self.name[key] @@ -157,6 +166,7 @@ class NameSpace(QualifiedName): result.append(name.name[i]) return NameSpace(result) + class Symbol(object): """ Symbols are defined as one of the following types: @@ -194,15 +204,21 @@ class Symbol(object): def __del__(self): core.BNFreeSymbol(self.handle) - def __eq__(self, value): - if not isinstance(value, Symbol): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + def __repr__(self): + return "<%s: \"%s\" @ %#x>" % (self.type, self.full_name, self.address) + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) - def __ne__(self, value): - if not isinstance(value, Symbol): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + def __hash__(self): + return hash(ctypes.addressof(self.handle.contents)) @property def type(self): @@ -270,15 +286,6 @@ class Symbol(object): core.BNFreeStringList(aliases, count) return result - def __repr__(self): - return "<%s: \"%s\" @ %#x>" % (self.type, self.full_name, self.address) - - def __setattr__(self, name, value): - try: - object.__setattr__(self, name, value) - except AttributeError: - raise AttributeError("attribute '%s' is read only" % name) - class FunctionParameter(object): def __init__(self, param_type, name = "", location = None): @@ -343,15 +350,34 @@ class Type(object): else: core.BNFreeType(self._handle) - def __eq__(self, value): - if not isinstance(value, Type): - return False - return core.BNTypesEqual(self.handle, value.handle) + def __repr__(self): + if self._confidence < max_confidence: + return "" % (str(self), (self._confidence * 100) // max_confidence) + return "" % str(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) + + def __len__(self): + return self.width + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return core.BNTypesEqual(self.handle, other.handle) - def __ne__(self, value): - if not isinstance(value, Type): - return True - return core.BNTypesNotEqual(self.handle, value.handle) + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return core.BNTypesNotEqual(self.handle, other.handle) @property def handle(self): @@ -595,25 +621,6 @@ class Type(object): return None return NamedTypeReference(handle = name) - def __len__(self): - return self.width - - 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) - - def __repr__(self): - if self._confidence < max_confidence: - return "" % (str(self), (self._confidence * 100) // max_confidence) - return "" % str(self) - def get_string_before_name(self): platform = None if self._platform is not None: @@ -868,7 +875,7 @@ class Type(object): return core.BNGetAutoDemangledTypeIdSource() def with_confidence(self, confidence): - return Type(handle = core.BNNewTypeReference(self.handle), platform = self._platform, confidence = confidence) + return Type(handle = core.BNNewTypeReference(self._handle), platform = self._platform, confidence = confidence) @property def confidence(self): @@ -894,13 +901,13 @@ class Type(object): 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)) + 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)) + 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)) + return Type(handle = core.BNTypeWithReplacedNamedTypeReference(self._handle, from_ref.handle, to_ref.handle)) class BoolWithConfidence(object): @@ -1087,15 +1094,29 @@ class NamedTypeReference(object): def __del__(self): core.BNFreeNamedTypeReference(self.handle) - def __eq__(self, value): - if not isinstance(value, NamedTypeReference): - return False - return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + def __repr__(self): + if self.type_class == NamedTypeReferenceClass.TypedefNamedTypeClass: + return "" % str(self.name) + if self.type_class == NamedTypeReferenceClass.StructNamedTypeClass: + return "" % str(self.name) + if self.type_class == NamedTypeReferenceClass.UnionNamedTypeClass: + return "" % str(self.name) + if self.type_class == NamedTypeReferenceClass.EnumNamedTypeClass: + return "" % str(self.name) + return "" % str(self.name) + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self.handle.contents) == ctypes.addressof(other.handle.contents) - def __ne__(self, value): - if not isinstance(value, NamedTypeReference): - return True - return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.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.handle.contents)) @property def type_class(self): @@ -1112,17 +1133,6 @@ class NamedTypeReference(object): core.BNFreeQualifiedName(name) return result - def __repr__(self): - if self.type_class == NamedTypeReferenceClass.TypedefNamedTypeClass: - return "" % str(self.name) - if self.type_class == NamedTypeReferenceClass.StructNamedTypeClass: - return "" % str(self.name) - if self.type_class == NamedTypeReferenceClass.UnionNamedTypeClass: - return "" % str(self.name) - if self.type_class == NamedTypeReferenceClass.EnumNamedTypeClass: - return "" % str(self.name) - return "" % str(self.name) - @classmethod def generate_auto_type_ref(self, type_class, source, name): type_id = Type.generate_auto_type_id(source, name) @@ -1146,6 +1156,39 @@ class StructureMember(object): return "<%s %s%s, offset %#x>" % (self._type.get_string_before_name(), self._name, self._type.get_string_after_name(), self._offset) + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return (self._type, self._name, self._offset) == (other._type, other._name, other._offset) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) + + def __lt__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self._offset < other._offset + + def __gt__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self._offset > other._offset + + def __le__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self._offset <= other._offset + + def __ge__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self._offset >= other._offset + + def __hash__(self): + return hash((self._type, self._name, self._offset)) + @property def type(self): """ """ @@ -1189,15 +1232,21 @@ class Structure(object): 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) + def __repr__(self): + return "" % self.width + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return ctypes.addressof(self._handle.contents) == ctypes.addressof(other.handle.contents) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) - def __ne__(self, value): - if not isinstance(value, Structure): - return True - return ctypes.addressof(self._handle.contents) != ctypes.addressof(value._handle.contents) + def __hash__(self): + return hash(ctypes.addressof(self._handle.contents)) def __getitem__(self, name): try: @@ -1304,9 +1353,6 @@ class Structure(object): raise AttributeError("Finalized Structure object is immutable, use mutable_copy()") core.BNSetStructureBuilderType(self._handle, value) - def __repr__(self): - return "" % self.width - def append(self, t, name = ""): if not self._mutable: raise AttributeError("Finalized Structure object is immutable, use mutable_copy()") @@ -1342,13 +1388,13 @@ class Structure(object): 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)) + 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)) + 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)) + return Structure(core.BNStructureWithReplacedNamedTypeReference(self._handle, from_ref.handle, to_ref.handle)) class EnumerationMember(object): @@ -1403,15 +1449,21 @@ class Enumeration(object): 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) + def __repr__(self): + return "" % 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) + + def __ne__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return not (self == other) - def __ne__(self, value): - if not isinstance(value, Enumeration): - return True - return ctypes.addressof(self._handle.contents) != ctypes.addressof(value._handle.contents) + def __hash__(self): + return hash(ctypes.addressof(self.handle.contents)) @property def handle(self): @@ -1437,9 +1489,6 @@ class Enumeration(object): core.BNFreeEnumerationMemberList(members, count.value) return result - def __repr__(self): - return "" % repr(self.members) - def append(self, name, value = None): if not self._mutable: raise AttributeError("Finalized Enumeration object is immutable, use mutable_copy()") -- cgit v1.3.1