From 1f6c09e54ab53403fe0236c46f69b896713abddc Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 16 Jan 2017 17:53:34 -0500 Subject: Fix lint issues --- python/architecture.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'python/architecture.py') diff --git a/python/architecture.py b/python/architecture.py index d67f00a6..32d97b09 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -364,7 +364,7 @@ class Architecture(object): 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")): + (name == "default_int_size") or (name == "regs") or (name == "get_max_instruction_length")): raise AttributeError("attribute '%s' is read only" % name) else: try: @@ -1610,7 +1610,7 @@ class Architecture(object): error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) if not result: - raise SyntaxError, error_str + raise SyntaxError(error_str) type_dict = {} variables = {} functions = {} @@ -1654,7 +1654,7 @@ class Architecture(object): error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) if not result: - raise SyntaxError, error_str + raise SyntaxError(error_str) type_dict = {} variables = {} functions = {} -- cgit v1.3.1 From ded271158000d7fa509f513b425d95390a7f2058 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 17 Jan 2017 18:44:51 -0500 Subject: Add missing Python APIs --- python/architecture.py | 6 ++++- python/basicblock.py | 4 +++- python/binaryview.py | 6 +++-- python/function.py | 19 ++++++++++++---- python/lowlevelil.py | 4 +++- python/types.py | 62 +++++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 90 insertions(+), 11 deletions(-) (limited to 'python/architecture.py') diff --git a/python/architecture.py b/python/architecture.py index 32d97b09..ea97f605 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -467,6 +467,8 @@ class Architecture(object): token_buf[i].value = tokens[i].value token_buf[i].size = tokens[i].size token_buf[i].operand = tokens[i].operand + token_buf[i].context = tokens[i].context + token_buf[i].address = tokens[i].address result[0] = token_buf ptr = ctypes.cast(token_buf, ctypes.c_void_p) self._pending_token_lists[ptr.value] = (ptr.value, token_buf) @@ -1148,7 +1150,9 @@ class Architecture(object): value = tokens[i].value size = tokens[i].size operand = tokens[i].operand - result.append(function.InstructionTextToken(token_type, text, value, size, operand)) + context = tokens[i].context + address = tokens[i].address + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) core.BNFreeInstructionText(tokens, count.value) return result, length.value diff --git a/python/basicblock.py b/python/basicblock.py index ae9889fc..ffbcd217 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -200,7 +200,9 @@ class BasicBlock(object): value = lines[i].tokens[j].value size = lines[i].tokens[j].size operand = lines[i].tokens[j].operand - tokens.append(function.InstructionTextToken(token_type, text, value, size, operand)) + context = lines[i].tokens[j].context + address = lines[i].tokens[j].address + tokens.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) result.append(function.DisassemblyTextLine(addr, tokens)) core.BNFreeDisassemblyTextLines(lines, count.value) return result diff --git a/python/binaryview.py b/python/binaryview.py index cf30d78d..f8fe1fde 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -1886,7 +1886,7 @@ class BinaryView(object): var = core.BNDataVariable() if not core.BNGetDataVariableAtAddress(self.handle, addr, var): return None - return DataVariable(var.address, type.Type(var.type), var.autoDiscovered) + return DataVariable(var.address, types.Type(var.type), var.autoDiscovered) def get_function_at(self, addr, plat=None): """ @@ -2750,7 +2750,9 @@ class BinaryView(object): value = lines[i].contents.tokens[j].value size = lines[i].contents.tokens[j].size operand = lines[i].contents.tokens[j].operand - tokens.append(function.InstructionTextToken(token_type, text, value, size, operand)) + context = lines[i].contents.tokens[j].context + address = lines[i].contents.tokens[j].address + tokens.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) contents = function.DisassemblyTextLine(addr, tokens) result.append(lineardisassembly.LinearDisassemblyLine(lines[i].type, func, block, lines[i].lineOffset, contents)) diff --git a/python/function.py b/python/function.py index 7d03585c..5f9f475a 100644 --- a/python/function.py +++ b/python/function.py @@ -26,7 +26,7 @@ import ctypes import _binaryninjacore as core from enums import (FunctionGraphType, BranchType, SymbolType, InstructionTextTokenType, HighlightStandardColor, HighlightColorStyle, RegisterValueType, ImplicitRegisterExtend, - DisassemblyOption, IntegerDisplayType) + DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext) import architecture import highlight import associateddatastore @@ -669,7 +669,9 @@ class Function(object): value = lines[i].tokens[j].value size = lines[i].tokens[j].size operand = lines[i].tokens[j].operand - tokens.append(InstructionTextToken(token_type, text, value, size, operand)) + context = lines[i].tokens[j].context + address = lines[i].tokens[j].address + tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address)) result.append(tokens) core.BNFreeInstructionTextLines(lines, count.value) return result @@ -916,7 +918,9 @@ class FunctionGraphBlock(object): value = lines[i].tokens[j].value size = lines[i].tokens[j].size operand = lines[i].tokens[j].operand - tokens.append(InstructionTextToken(token_type, text, value, size, operand)) + context = lines[i].tokens[j].context + address = lines[i].tokens[j].address + tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address)) result.append(DisassemblyTextLine(addr, tokens)) core.BNFreeDisassemblyTextLines(lines, count.value) return result @@ -966,7 +970,9 @@ class FunctionGraphBlock(object): value = lines[i].tokens[j].value size = lines[i].tokens[j].size operand = lines[i].tokens[j].operand - tokens.append(InstructionTextToken(token_type, text, value, size, operand)) + context = lines[i].tokens[j].context + address = lines[i].tokens[j].address + tokens.append(InstructionTextToken(token_type, text, value, size, operand, context, address)) yield DisassemblyTextLine(addr, tokens) finally: core.BNFreeDisassemblyTextLines(lines, count.value) @@ -1237,12 +1243,15 @@ class InstructionTextToken(object): ========================== ============================================ """ - def __init__(self, token_type, text, value = 0, size = 0, operand = 0xffffffff): + def __init__(self, token_type, text, value = 0, size = 0, operand = 0xffffffff, + context = InstructionTextTokenContext.NoTokenContext, address = 0): self.type = InstructionTextTokenType(token_type) self.text = text self.value = value self.size = size self.operand = operand + self.context = InstructionTextTokenContext(context) + self.address = address def __str__(self): return self.text diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 419e8513..29b46b65 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -187,7 +187,9 @@ class LowLevelILInstruction(object): value = tokens[i].value size = tokens[i].size operand = tokens[i].operand - result.append(function.InstructionTextToken(token_type, text, value, size, operand)) + context = tokens[i].context + address = tokens[i].address + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) core.BNFreeInstructionText(tokens, count.value) return result diff --git a/python/types.py b/python/types.py index 0470ea73..1dd2157e 100644 --- a/python/types.py +++ b/python/types.py @@ -22,8 +22,9 @@ import ctypes # Binary Ninja components import _binaryninjacore as core -from enums import SymbolType, TypeClass, NamedTypeReferenceClass +from enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType import callingconvention +import function class QualifiedName(object): @@ -317,6 +318,56 @@ class Type(object): def get_string_after_name(self): return core.BNGetTypeStringAfterName(self.handle) + @property + def tokens(self): + """Type string as a list of tokens (read-only)""" + count = ctypes.c_ulonglong() + tokens = core.BNGetTypeTokens(self.handle, count) + result = [] + for i in xrange(0, count.value): + token_type = InstructionTextTokenType(tokens[i].type) + text = tokens[i].text + value = tokens[i].value + size = tokens[i].size + operand = tokens[i].operand + context = tokens[i].context + address = tokens[i].address + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + core.BNFreeTokenList(tokens, count.value) + return result + + def get_tokens_before_name(self): + count = ctypes.c_ulonglong() + tokens = core.BNGetTypeTokensBeforeName(self.handle, count) + result = [] + for i in xrange(0, count.value): + token_type = InstructionTextTokenType(tokens[i].type) + text = tokens[i].text + value = tokens[i].value + size = tokens[i].size + operand = tokens[i].operand + context = tokens[i].context + address = tokens[i].address + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + core.BNFreeTokenList(tokens, count.value) + return result + + def get_tokens_after_name(self): + count = ctypes.c_ulonglong() + tokens = core.BNGetTypeTokensAfterName(self.handle, count) + result = [] + for i in xrange(0, count.value): + token_type = InstructionTextTokenType(tokens[i].type) + text = tokens[i].text + value = tokens[i].value + size = tokens[i].size + operand = tokens[i].operand + context = tokens[i].context + address = tokens[i].address + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + core.BNFreeTokenList(tokens, count.value) + return result + @classmethod def void(cls): return Type(core.BNCreateVoidType()) @@ -518,6 +569,9 @@ class Structure(object): def remove(self, i): core.BNRemoveStructureMember(self.handle, i) + def replace(self, i, t, name = ""): + core.BNReplaceStructureMember(self.handle, i, t.handle, name) + class EnumerationMember(object): def __init__(self, name, value, default): @@ -565,6 +619,12 @@ class Enumeration(object): else: core.BNAddEnumerationMemberWithValue(self.handle, name, value) + def remove(self, i): + core.BNRemoveEnumerationMember(self.handle, i) + + def replace(self, i, name, value): + core.BNReplaceEnumerationMember(self.handle, i, name, value) + class TypeParserResult(object): def __init__(self, types, variables, functions): -- cgit v1.3.1 From 898ec98d9858ddec7fb431ba304d996cec12ff68 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 9 Feb 2017 19:06:07 -0500 Subject: APIs for handling platform types --- architecture.cpp | 9 +++++---- binaryninjaapi.h | 17 ++++++++++++----- binaryninjacore.h | 16 ++++++++++------ binaryview.cpp | 6 ++++++ platform.cpp | 28 ++++++++++++++++++++++++++++ python/architecture.py | 12 ++++++++---- python/binaryview.py | 16 ++++++++++++++++ python/platform.py | 12 ++++++++++++ python/types.py | 18 ++++++------------ type.cpp | 26 +++++++++++--------------- 10 files changed, 114 insertions(+), 46 deletions(-) (limited to 'python/architecture.py') diff --git a/architecture.cpp b/architecture.cpp index 0e25fa85..d72e7f42 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -747,7 +747,8 @@ void Architecture::SetBinaryViewTypeConstant(const string& type, const string& n bool Architecture::ParseTypesFromSource(const string& source, const string& fileName, map>& types, map>& variables, - map>& functions, string& errors, const vector& includeDirs) + map>& functions, string& errors, const vector& includeDirs, + const string& autoTypeSource) { BNTypeParserResult result; char* errorStr; @@ -761,7 +762,7 @@ bool Architecture::ParseTypesFromSource(const string& source, const string& file functions.clear(); bool ok = BNParseTypesFromSource(m_object, source.c_str(), fileName.c_str(), &result, - &errorStr, includeDirList, includeDirs.size()); + &errorStr, includeDirList, includeDirs.size(), autoTypeSource.c_str()); errors = errorStr; BNFreeString(errorStr); if (!ok) @@ -789,7 +790,7 @@ bool Architecture::ParseTypesFromSource(const string& source, const string& file bool Architecture::ParseTypesFromSourceFile(const string& fileName, map>& types, map>& variables, map>& functions, - string& errors, const vector& includeDirs) + string& errors, const vector& includeDirs, const string& autoTypeSource) { BNTypeParserResult result; char* errorStr; @@ -803,7 +804,7 @@ bool Architecture::ParseTypesFromSourceFile(const string& fileName, map>& types, std::map>& variables, std::map>& functions, std::string& errors, - const std::vector& includeDirs = std::vector()); + const std::vector& includeDirs = std::vector(), + const std::string& autoTypeSource = ""); bool ParseTypesFromSourceFile(const std::string& fileName, std::map>& types, std::map>& variables, std::map>& functions, std::string& errors, - const std::vector& includeDirs = std::vector()); + const std::vector& includeDirs = std::vector(), + const std::string& autoTypeSource = ""); void RegisterCallingConvention(CallingConvention* cc); std::vector> GetCallingConventions(); @@ -1627,8 +1631,8 @@ namespace BinaryNinja const std::vector& params, bool varArg = false); static std::string GenerateAutoTypeId(const std::string& source, const QualifiedName& name); - static std::string GenerateAutoPlatformTypeId(const QualifiedName& name); static std::string GenerateAutoDemangledTypeId(const QualifiedName& name); + static std::string GetAutoDemangledTypeIdSource(); }; class NamedTypeReference: public CoreRefCountObject GenerateAutoTypeReference(BNNamedTypeReferenceClass cls, const std::string& source, const QualifiedName& name); - static Ref GenerateAutoPlatformTypeReference(BNNamedTypeReferenceClass cls, - const QualifiedName& name); static Ref GenerateAutoDemangledTypeReference(BNNamedTypeReferenceClass cls, const QualifiedName& name); }; @@ -2339,6 +2341,11 @@ namespace BinaryNinja Ref GetRelatedPlatform(Architecture* arch); void AddRelatedPlatform(Architecture* arch, Platform* platform); Ref GetAssociatedPlatformByAddress(uint64_t& addr); + + std::string GenerateAutoPlatformTypeId(const QualifiedName& name); + Ref GenerateAutoPlatformTypeReference(BNNamedTypeReferenceClass cls, + const QualifiedName& name); + std::string GetAutoPlatformTypeIdSource(); }; class ScriptingOutputListener diff --git a/binaryninjacore.h b/binaryninjacore.h index b454da64..4b810002 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1820,8 +1820,12 @@ extern "C" BINARYNINJACOREAPI void BNUndefineUserAnalysisType(BNBinaryView* view, BNQualifiedName* name); BINARYNINJACOREAPI void BNRenameAnalysisType(BNBinaryView* view, BNQualifiedName* oldName, BNQualifiedName* newName); BINARYNINJACOREAPI char* BNGenerateAutoTypeId(const char* source, BNQualifiedName* name); - BINARYNINJACOREAPI char* BNGenerateAutoPlatformTypeId(BNQualifiedName* name); + BINARYNINJACOREAPI char* BNGenerateAutoPlatformTypeId(BNPlatform* platform, BNQualifiedName* name); BINARYNINJACOREAPI char* BNGenerateAutoDemangledTypeId(BNQualifiedName* name); + BINARYNINJACOREAPI char* BNGetAutoPlatformTypeIdSource(BNPlatform* platform); + BINARYNINJACOREAPI char* BNGetAutoDemangledTypeIdSource(void); + + BINARYNINJACOREAPI void BNRegisterPlatformTypes(BNBinaryView* view, BNPlatform* platform); BINARYNINJACOREAPI void BNReanalyzeAllFunctions(BNBinaryView* view); BINARYNINJACOREAPI void BNReanalyzeFunction(BNFunction* func); @@ -2063,13 +2067,13 @@ extern "C" // Source code processing BINARYNINJACOREAPI bool BNPreprocessSource(const char* source, const char* fileName, char** output, char** errors, - const char** includeDirs, size_t includeDirCount); + const char** includeDirs, size_t includeDirCount); BINARYNINJACOREAPI bool BNParseTypesFromSource(BNArchitecture* arch, const char* source, const char* fileName, - BNTypeParserResult* result, char** errors, - const char** includeDirs, size_t includeDirCount); + BNTypeParserResult* result, char** errors, const char** includeDirs, size_t includeDirCount, + const char* autoTypeSource); BINARYNINJACOREAPI bool BNParseTypesFromSourceFile(BNArchitecture* arch, const char* fileName, - BNTypeParserResult* result, char** errors, - const char** includeDirs, size_t includeDirCount); + BNTypeParserResult* result, char** errors, const char** includeDirs, size_t includeDirCount, + const char* autoTypeSource); BINARYNINJACOREAPI void BNFreeTypeParserResult(BNTypeParserResult* result); // Updates diff --git a/binaryview.cpp b/binaryview.cpp index 1b1574e1..8edbc2bf 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1577,6 +1577,12 @@ void BinaryView::RenameType(const QualifiedName& oldName, const QualifiedName& n } +void BinaryView::RegisterPlatformTypes(Platform* platform) +{ + BNRegisterPlatformTypes(m_object, platform->GetObject()); +} + + bool BinaryView::FindNextData(uint64_t start, const DataBuffer& data, uint64_t& result, BNFindFlag flags) { return BNFindNextData(m_object, start, data.GetBufferObject(), &result, flags); diff --git a/platform.cpp b/platform.cpp index 7a6571cc..3bf4c0a4 100644 --- a/platform.cpp +++ b/platform.cpp @@ -253,3 +253,31 @@ Ref Platform::GetAssociatedPlatformByAddress(uint64_t& addr) return nullptr; return new Platform(platform); } + + +string Platform::GenerateAutoPlatformTypeId(const QualifiedName& name) +{ + BNQualifiedName nameObj = name.GetAPIObject(); + char* str = BNGenerateAutoPlatformTypeId(m_object, &nameObj); + string result = str; + QualifiedName::FreeAPIObject(&nameObj); + BNFreeString(str); + return result; +} + + +Ref Platform::GenerateAutoPlatformTypeReference(BNNamedTypeReferenceClass cls, + const QualifiedName& name) +{ + string id = GenerateAutoPlatformTypeId(name); + return new NamedTypeReference(cls, id, name); +} + + +string Platform::GetAutoPlatformTypeIdSource() +{ + char* str = BNGetAutoPlatformTypeIdSource(m_object); + string result = str; + BNFreeString(str); + return result; +} diff --git a/python/architecture.py b/python/architecture.py index ea97f605..4cd0c597 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -1585,7 +1585,7 @@ class Architecture(object): """ core.BNSetBinaryViewTypeArchitectureConstant(self.handle, type_name, const_name, value) - def parse_types_from_source(self, source, filename=None, include_dirs=[]): + def parse_types_from_source(self, source, filename=None, include_dirs=[], auto_type_source=None): """ ``parse_types_from_source`` parses the source string and any needed headers searching for them in the optional list of directories provided in ``include_dirs``. @@ -1593,6 +1593,7 @@ class Architecture(object): :param str source: source string to be parsed :param str filename: optional source filename :param list(str) include_dirs: optional list of string filename include directories + :param str auto_type_source: optional source of types if used for automatically generated types :return: py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) :rtype: TypeParserResult :Example: @@ -1610,7 +1611,8 @@ class Architecture(object): dir_buf[i] = str(include_dirs[i]) parse = core.BNTypeParserResult() errors = ctypes.c_char_p() - result = core.BNParseTypesFromSource(self.handle, source, filename, parse, errors, dir_buf, len(include_dirs)) + result = core.BNParseTypesFromSource(self.handle, source, filename, parse, errors, dir_buf, + len(include_dirs), auto_type_source) error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) if not result: @@ -1630,13 +1632,14 @@ class Architecture(object): core.BNFreeTypeParserResult(parse) return types.TypeParserResult(type_dict, variables, functions) - def parse_types_from_source_file(self, filename, include_dirs=[]): + def parse_types_from_source_file(self, filename, include_dirs=[], auto_type_source=None): """ ``parse_types_from_source_file`` parses the source file ``filename`` and any needed headers searching for them in the optional list of directories provided in ``include_dirs``. :param str filename: filename of file to be parsed :param list(str) include_dirs: optional list of string filename include directories + :param str auto_type_source: optional source of types if used for automatically generated types :return: py:class:`TypeParserResult` (a SyntaxError is thrown on parse error) :rtype: TypeParserResult :Example: @@ -1654,7 +1657,8 @@ class Architecture(object): dir_buf[i] = str(include_dirs[i]) parse = core.BNTypeParserResult() errors = ctypes.c_char_p() - result = core.BNParseTypesFromSourceFile(self.handle, filename, parse, errors, dir_buf, len(include_dirs)) + result = core.BNParseTypesFromSourceFile(self.handle, filename, parse, errors, dir_buf, + len(include_dirs), auto_type_source) error_str = errors.value core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) if not result: diff --git a/python/binaryview.py b/python/binaryview.py index 2cdacb4c..caa5d780 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -3077,6 +3077,22 @@ class BinaryView(object): new_name = types.QualifiedName(new_name)._get_core_struct() core.BNRenameAnalysisType(self.handle, old_name, new_name) + def register_platform_types(self, platform): + """ + ``register_platform_types`` ensures that the platform-specific types for a :py:Class:`Platform` are available + for the current :py:Class:`BinaryView`. This is automatically performed when adding a new function or setting + the default platform. + + :param Platform platform: Platform containing types to be registered + :rtype: None + :Example: + + >>> platform = Platform["linux-x86"] + >>> bv.register_platform_types(platform) + >>> + """ + core.BNRegisterPlatformTypes(self.handle, platform.handle) + def find_next_data(self, start, data, flags = 0): """ ``find_next_data`` searchs for the bytes in data starting at the virtual address ``start`` either, case-sensitive, diff --git a/python/platform.py b/python/platform.py index 04dce587..5d90997d 100644 --- a/python/platform.py +++ b/python/platform.py @@ -25,6 +25,7 @@ import _binaryninjacore as core import startup import architecture import callingconvention +import types class _PlatformMetaClass(type): @@ -259,3 +260,14 @@ class Platform(object): new_addr.value = addr result = core.BNGetAssociatedPlatformByAddress(self.handle, new_addr) return Platform(None, handle = result), new_addr.value + + def generate_auto_platform_type_id(self, name): + name = types.QualifiedName(name)._get_core_struct() + return core.BNGenerateAutoPlatformTypeId(self.handle, name) + + def generate_auto_platform_type_ref(self, type_class, name): + type_id = self.generate_auto_platform_type_id(name) + return types.NamedTypeReference(type_class, type_id, name) + + def get_auto_platform_type_id_source(self): + return core.BNGetAutoPlatformTypeIdSource(self.handle) diff --git a/python/types.py b/python/types.py index 1cc02691..f66625f8 100644 --- a/python/types.py +++ b/python/types.py @@ -446,14 +446,13 @@ class Type(object): return core.BNGenerateAutoTypeId(source, name) @classmethod - def generate_auto_platform_type_id(self, name): + def generate_auto_demangled_type_id(self, name): name = QualifiedName(name)._get_core_struct() - return core.BNGenerateAutoTypeId(name) + return core.BNGenerateAutoDemangledTypeId(name) @classmethod - def generate_auto_demangled_type_id(self, name): - name = QualifiedName(name)._get_core_struct() - return core.BNGenerateAutoTypeId(name) + def get_auto_demanged_type_id_source(self): + return core.BNGetAutoDemangledTypeIdSource() def __setattr__(self, name, value): try: @@ -523,13 +522,8 @@ class NamedTypeReference(object): return NamedTypeReference(type_class, type_id, name) @classmethod - def generate_auto_platform_type_ref(self, type_class, source, name): - type_id = Type.generate_auto_platform_type_id(source, name) - return NamedTypeReference(type_class, type_id, name) - - @classmethod - def generate_auto_demangled_type_ref(self, type_class, source, name): - type_id = Type.generate_auto_demangled_type_id(source, name) + def generate_auto_demangled_type_ref(self, type_class, name): + type_id = Type.generate_auto_demangled_type_id(name) return NamedTypeReference(type_class, type_id, name) diff --git a/type.cpp b/type.cpp index dd1fb8d6..66138001 100644 --- a/type.cpp +++ b/type.cpp @@ -580,26 +580,30 @@ void Type::SetFunctionCanReturn(bool canReturn) string Type::GenerateAutoTypeId(const string& source, const QualifiedName& name) { BNQualifiedName nameObj = name.GetAPIObject(); - string result = BNGenerateAutoTypeId(source.c_str(), &nameObj); + char* str = BNGenerateAutoTypeId(source.c_str(), &nameObj); + string result = str; QualifiedName::FreeAPIObject(&nameObj); + BNFreeString(str); return result; } -string Type::GenerateAutoPlatformTypeId(const QualifiedName& name) +string Type::GenerateAutoDemangledTypeId(const QualifiedName& name) { BNQualifiedName nameObj = name.GetAPIObject(); - string result = BNGenerateAutoPlatformTypeId(&nameObj); + char* str = BNGenerateAutoDemangledTypeId(&nameObj); + string result = str; QualifiedName::FreeAPIObject(&nameObj); + BNFreeString(str); return result; } -string Type::GenerateAutoDemangledTypeId(const QualifiedName& name) +string Type::GetAutoDemangledTypeIdSource() { - BNQualifiedName nameObj = name.GetAPIObject(); - string result = BNGenerateAutoDemangledTypeId(&nameObj); - QualifiedName::FreeAPIObject(&nameObj); + char* str = BNGetAutoDemangledTypeIdSource(); + string result = str; + BNFreeString(str); return result; } @@ -679,14 +683,6 @@ Ref NamedTypeReference::GenerateAutoTypeReference(BNNamedTyp } -Ref NamedTypeReference::GenerateAutoPlatformTypeReference(BNNamedTypeReferenceClass cls, - const QualifiedName& name) -{ - string id = Type::GenerateAutoPlatformTypeId(name); - return new NamedTypeReference(cls, id, name); -} - - Ref NamedTypeReference::GenerateAutoDemangledTypeReference(BNNamedTypeReferenceClass cls, const QualifiedName& name) { -- cgit v1.3.1 From f8687791c32688a78b5e6667b2af9689816e41af Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Fri, 10 Feb 2017 16:37:32 -0500 Subject: Merge in pull requests that never made it into dev --- python/architecture.py | 4 ++-- python/binaryview.py | 2 +- python/types.py | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 3 deletions(-) (limited to 'python/architecture.py') diff --git a/python/architecture.py b/python/architecture.py index f1440ca3..3e899d68 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -1160,8 +1160,8 @@ class Architecture(object): def get_instruction_low_level_il(self, data, addr, il): """ - ``get_instruction_low_level_il`` appends LowLevelILExpr objects for the instruction at the given virtual - address ``addr`` with data ``data``. + ``get_instruction_low_level_il`` appends LowLevelILExpr objects to ``il`` for the instruction at the given + virtual address ``addr`` with data ``data``. :param str data: max_instruction_length bytes from the binary at virtual address ``addr`` :param int addr: virtual address of bytes in ``data`` diff --git a/python/binaryview.py b/python/binaryview.py index 476f2be6..c021024f 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -1933,7 +1933,7 @@ class BinaryView(object): def get_basic_blocks_starting_at(self, addr): """ - ``get_basic_blocks_at`` get a list of :py:Class:`BasicBlock` objects which start at the provided virtual address. + ``get_basic_blocks_starting_at`` get a list of :py:Class:`BasicBlock` objects which start at the provided virtual address. :param int addr: virtual address of BasicBlock desired :return: a list of :py:Class:`BasicBlock` objects diff --git a/python/types.py b/python/types.py index 8582e4e0..62a441cd 100644 --- a/python/types.py +++ b/python/types.py @@ -237,6 +237,12 @@ class Type(object): @classmethod def int(self, width, sign = True, altname=""): + """ + ``int`` class method for creating an int Type. + + :param int width: width of the integer in bytes + :param bool sign: optional variable representing signedness + """ return Type(core.BNCreateIntegerType(width, sign, altname)) @classmethod @@ -267,6 +273,14 @@ class Type(object): @classmethod def function(self, ret, params, calling_convention=None, variable_arguments=False): + """ + ``function`` class method for creating an function Type. + + :param Type ret: width of the integer in bytes + :param list(Type) params: list of parameter Types + :param CallingConvention calling_convention: optional argument for function calling convention + :param bool variable_arguments: optional argument for functions that have a variable number of arguments + """ param_buf = (core.BNNameAndType * len(params))() for i in xrange(0, len(params)): if isinstance(params[i], Type): -- cgit v1.3.1 From 57c08987ee10af0b52d5c3fd44739a3935f9efa7 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 16 Feb 2017 19:12:43 -0500 Subject: Basic blocks have incoming and outgoing edges with basic block references, use core object identity for equality --- basicblock.cpp | 30 +++++++++++++++++++++--- binaryninjaapi.h | 42 ++++++++++++++++++++++++++++++---- binaryninjacore.h | 7 +++--- python/architecture.py | 10 ++++++++ python/basicblock.py | 56 +++++++++++++++++++++++++++++++++------------ python/binaryview.py | 40 ++++++++++++++++++++++++++++++++ python/callingconvention.py | 10 ++++++++ python/filemetadata.py | 10 ++++++++ python/function.py | 30 ++++++++++++++++++++++++ python/lowlevelil.py | 10 ++++++++ python/platform.py | 10 ++++++++ python/transform.py | 10 ++++++++ python/types.py | 50 ++++++++++++++++++++++++++++++++++++++++ 13 files changed, 291 insertions(+), 24 deletions(-) (limited to 'python/architecture.py') diff --git a/basicblock.cpp b/basicblock.cpp index 4edcc568..153a7768 100644 --- a/basicblock.cpp +++ b/basicblock.cpp @@ -108,6 +108,12 @@ uint64_t BasicBlock::GetLength() const } +size_t BasicBlock::GetIndex() const +{ + return BNGetBasicBlockIndex(m_object); +} + + vector BasicBlock::GetOutgoingEdges() const { size_t count; @@ -118,12 +124,30 @@ vector BasicBlock::GetOutgoingEdges() const { BasicBlockEdge edge; edge.type = array[i].type; - edge.target = array[i].target; - edge.arch = array[i].arch ? new CoreArchitecture(array[i].arch) : nullptr; + edge.target = array[i].target ? new BasicBlock(BNNewBasicBlockReference(array[i].target)) : nullptr; + result.push_back(edge); + } + + BNFreeBasicBlockEdgeList(array, count); + return result; +} + + +vector BasicBlock::GetIncomingEdges() const +{ + size_t count; + BNBasicBlockEdge* array = BNGetBasicBlockIncomingEdges(m_object, &count); + + vector result; + for (size_t i = 0; i < count; i++) + { + BasicBlockEdge edge; + edge.type = array[i].type; + edge.target = array[i].target ? new BasicBlock(BNNewBasicBlockReference(array[i].target)) : nullptr; result.push_back(edge); } - BNFreeBasicBlockOutgoingEdgeList(array); + BNFreeBasicBlockEdgeList(array, count); return result; } diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 370a9ae2..7004501c 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -51,6 +51,8 @@ namespace BinaryNinja RefCountObject(): m_refs(0) {} virtual ~RefCountObject() {} + RefCountObject* GetObject() { return this; } + void AddRef() { #ifdef WIN32 @@ -101,7 +103,7 @@ namespace BinaryNinja CoreRefCountObject(): m_refs(0), m_object(nullptr) {} virtual ~CoreRefCountObject() {} - T* GetObject() { return m_object; } + T* GetObject() const { return m_object; } void AddRef() { @@ -158,7 +160,7 @@ namespace BinaryNinja StaticCoreRefCountObject(): m_refs(0), m_object(nullptr) {} virtual ~StaticCoreRefCountObject() {} - T* GetObject() { return m_object; } + T* GetObject() const { return m_object; } void AddRef() { @@ -246,6 +248,36 @@ namespace BinaryNinja return m_obj == NULL; } + bool operator==(const T* obj) const + { + return m_obj->GetObject() == obj->GetObject(); + } + + bool operator==(const Ref& obj) const + { + return m_obj->GetObject() == obj.m_obj->GetObject(); + } + + bool operator!=(const T* obj) const + { + return m_obj->GetObject() != obj->GetObject(); + } + + bool operator!=(const Ref& obj) const + { + return m_obj->GetObject() != obj.m_obj->GetObject(); + } + + bool operator<(const T* obj) const + { + return m_obj->GetObject() < obj->GetObject(); + } + + bool operator<(const Ref& obj) const + { + return m_obj->GetObject() < obj.m_obj->GetObject(); + } + T* GetPtr() const { return m_obj; @@ -1728,8 +1760,7 @@ namespace BinaryNinja struct BasicBlockEdge { BNBranchType type; - uint64_t target; - Ref arch; + Ref target; }; class BasicBlock: public CoreRefCountObject @@ -1744,7 +1775,10 @@ namespace BinaryNinja uint64_t GetEnd() const; uint64_t GetLength() const; + size_t GetIndex() const; + std::vector GetOutgoingEdges() const; + std::vector GetIncomingEdges() const; bool HasUndeterminedOutgoingEdges() const; void MarkRecentUse(); diff --git a/binaryninjacore.h b/binaryninjacore.h index b8531742..2d22bb3f 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -793,8 +793,7 @@ extern "C" struct BNBasicBlockEdge { BNBranchType type; - uint64_t target; - BNArchitecture* arch; + BNBasicBlock* target; }; struct BNPoint @@ -1726,8 +1725,10 @@ extern "C" BINARYNINJACOREAPI uint64_t BNGetBasicBlockEnd(BNBasicBlock* block); BINARYNINJACOREAPI uint64_t BNGetBasicBlockLength(BNBasicBlock* block); BINARYNINJACOREAPI BNBasicBlockEdge* BNGetBasicBlockOutgoingEdges(BNBasicBlock* block, size_t* count); - BINARYNINJACOREAPI void BNFreeBasicBlockOutgoingEdgeList(BNBasicBlockEdge* edges); + BINARYNINJACOREAPI BNBasicBlockEdge* BNGetBasicBlockIncomingEdges(BNBasicBlock* block, size_t* count); + BINARYNINJACOREAPI void BNFreeBasicBlockEdgeList(BNBasicBlockEdge* edges, size_t count); BINARYNINJACOREAPI bool BNBasicBlockHasUndeterminedOutgoingEdges(BNBasicBlock* block); + BINARYNINJACOREAPI size_t BNGetBasicBlockIndex(BNBasicBlock* block); BINARYNINJACOREAPI BNDisassemblyTextLine* BNGetBasicBlockDisassemblyText(BNBasicBlock* block, BNDisassemblySettings* settings, size_t* count); diff --git a/python/architecture.py b/python/architecture.py index 5bafe949..39e5e72d 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -333,6 +333,16 @@ class Architecture(object): self._pending_reg_lists = {} self._pending_token_lists = {} + def __eq__(self, value): + if not isinstance(value, Architecture): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, Architecture): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def full_width_regs(self): """List of full width register strings (read-only)""" diff --git a/python/basicblock.py b/python/basicblock.py index f6dbd60d..ebacb311 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -29,19 +29,17 @@ import function class BasicBlockEdge(object): - def __init__(self, branch_type, target, arch): + def __init__(self, branch_type, target): self.type = branch_type - if self.type != BranchType.UnresolvedBranch: - self.target = target - self.arch = arch + self.target = target def __repr__(self): if self.type == BranchType.UnresolvedBranch: return "<%s>" % BranchType(self.type).name - elif self.arch: - return "<%s: %s@%#x>" % (self.type, self.arch.name, self.target) + elif self.target.arch: + return "<%s: %s@%#x>" % (BranchType(self.type).name, self.target.arch.name, self.target.start) else: - return "<%s: %#x>" % (self.type, self.target) + return "<%s: %#x>" % (BranchType(self.type).name, self.target.start) class BasicBlock(object): @@ -52,6 +50,16 @@ 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 __ne__(self, value): + if not isinstance(value, BasicBlock): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def function(self): """Basic block function (read-only)""" @@ -83,6 +91,11 @@ class BasicBlock(object): """Basic block length (read-only)""" return core.BNGetBasicBlockLength(self.handle) + @property + def index(self): + """Basic block index in list of blocks for the function (read-only)""" + return core.BNGetBasicBlockIndex(self.handle) + @property def outgoing_edges(self): """List of basic block outgoing edges (read-only)""" @@ -90,14 +103,29 @@ class BasicBlock(object): edges = core.BNGetBasicBlockOutgoingEdges(self.handle, count) result = [] for i in xrange(0, count.value): - branch_type = edges[i].type - target = edges[i].target - if edges[i].arch: - arch = architecture.Architecture(edges[i].arch) + branch_type = BranchType(edges[i].type) + if edges[i].target: + target = BasicBlock(self.view, core.BNNewBasicBlockReference(edges[i].target)) + else: + target = None + result.append(BasicBlockEdge(branch_type, target)) + core.BNFreeBasicBlockEdgeList(edges, count.value) + return result + + @property + def incoming_edges(self): + """List of basic block incoming edges (read-only)""" + count = ctypes.c_ulonglong(0) + edges = core.BNGetBasicBlockIncomingEdges(self.handle, count) + result = [] + for i in xrange(0, count.value): + branch_type = BranchType(edges[i].type) + if edges[i].target: + target = BasicBlock(self.view, core.BNNewBasicBlockReference(edges[i].target)) else: - arch = None - result.append(BasicBlockEdge(branch_type, target, arch)) - core.BNFreeBasicBlockOutgoingEdgeList(edges) + target = None + result.append(BasicBlockEdge(branch_type, target)) + core.BNFreeBasicBlockEdgeList(edges, count.value) return result @property diff --git a/python/binaryview.py b/python/binaryview.py index 9753b653..dd37be69 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -299,6 +299,16 @@ class BinaryViewType(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 __ne__(self, value): + if not isinstance(value, BinaryViewType): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def name(self): """BinaryView name (read-only)""" @@ -547,6 +557,16 @@ 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 __ne__(self, value): + if not isinstance(value, BinaryView): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @classmethod def register(cls): startup._init_plugins() @@ -3255,6 +3275,16 @@ 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 __ne__(self, value): + if not isinstance(value, BinaryReader): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def endianness(self): """ @@ -3562,6 +3592,16 @@ 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 __ne__(self, value): + if not isinstance(value, BinaryWriter): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def endianness(self): """ diff --git a/python/callingconvention.py b/python/callingconvention.py index 5f4adeab..04ba711f 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -112,6 +112,16 @@ class CallingConvention(object): def __del__(self): 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 __ne__(self, value): + if not isinstance(value, CallingConvention): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + def _get_caller_saved_regs(self, ctxt, count): try: regs = self.__class__.caller_saved_regs diff --git a/python/filemetadata.py b/python/filemetadata.py index f6593405..b489d5bb 100644 --- a/python/filemetadata.py +++ b/python/filemetadata.py @@ -93,6 +93,16 @@ class FileMetadata(object): 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) diff --git a/python/function.py b/python/function.py index 3aeb8e22..4cdd6cc9 100644 --- a/python/function.py +++ b/python/function.py @@ -177,6 +177,16 @@ class Function(object): core.BNReleaseAdvancedFunctionAnalysisDataMultiple(self.handle, self._advanced_analysis_requests) core.BNFreeFunction(self.handle) + def __eq__(self, value): + if not isinstance(value, Function): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, Function): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @classmethod def _unregister(cls, func): handle = ctypes.cast(func, ctypes.c_void_p) @@ -856,6 +866,16 @@ class FunctionGraphBlock(object): def __del__(self): core.BNFreeFunctionGraphBlock(self.handle) + def __eq__(self, value): + if not isinstance(value, FunctionGraphBlock): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, FunctionGraphBlock): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def basic_block(self): """Basic block associated with this part of the function graph (read-only)""" @@ -1030,6 +1050,16 @@ class FunctionGraph(object): self.abort() core.BNFreeFunctionGraph(self.handle) + def __eq__(self, value): + if not isinstance(value, FunctionGraph): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, FunctionGraph): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def function(self): """Function for a function graph (read-only)""" diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 29b46b65..c80fcd0d 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -253,6 +253,16 @@ class LowLevelILFunction(object): def __del__(self): core.BNFreeLowLevelILFunction(self.handle) + def __eq__(self, value): + if not isinstance(value, LowLevelILFunction): + 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) + @property def current_address(self): """Current IL Address (read/write)""" diff --git a/python/platform.py b/python/platform.py index ccc80476..139b7d5e 100644 --- a/python/platform.py +++ b/python/platform.py @@ -110,6 +110,16 @@ class Platform(object): def __del__(self): 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 __ne__(self, value): + if not isinstance(value, Platform): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def default_calling_convention(self): """ diff --git a/python/transform.py b/python/transform.py index 0c003738..40382c69 100644 --- a/python/transform.py +++ b/python/transform.py @@ -131,6 +131,16 @@ class Transform(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 __ne__(self, value): + if not isinstance(value, Transform): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + def _get_parameters(self, ctxt, count): try: count[0] = len(self.parameters) diff --git a/python/types.py b/python/types.py index 43aaa66f..ebaa36fc 100644 --- a/python/types.py +++ b/python/types.py @@ -139,6 +139,16 @@ 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 __ne__(self, value): + if not isinstance(value, Symbol): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def type(self): """Symbol type (read-only)""" @@ -194,6 +204,16 @@ class Type(object): def __del__(self): core.BNFreeType(self.handle) + def __eq__(self, value): + if not isinstance(value, Type): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, Type): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def type_class(self): """Type class (read-only)""" @@ -491,6 +511,16 @@ 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 __ne__(self, value): + if not isinstance(value, NamedTypeReference): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def type_class(self): return NamedTypeReferenceClass(core.BNGetTypeReferenceClass(self.handle)) @@ -564,6 +594,16 @@ class Structure(object): def __del__(self): 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 __ne__(self, value): + if not isinstance(value, Structure): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def members(self): """Structure member list (read-only)""" @@ -652,6 +692,16 @@ class Enumeration(object): def __del__(self): 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 __ne__(self, value): + if not isinstance(value, Enumeration): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property def members(self): """Enumeration member list (read-only)""" -- cgit v1.3.1