summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/__init__.py7
-rw-r--r--python/architecture.py15
-rw-r--r--python/basicblock.py11
-rw-r--r--python/binaryview.py56
-rw-r--r--python/examples/nes.py1
-rw-r--r--python/function.py86
-rw-r--r--python/functionrecognizer.py15
-rw-r--r--python/interaction.py2
-rw-r--r--python/lowlevelil.py3
-rw-r--r--python/mediumlevelil.py9
-rw-r--r--python/pluginmanager.py1
-rw-r--r--python/scriptingprovider.py23
-rw-r--r--python/update.py2
13 files changed, 196 insertions, 35 deletions
diff --git a/python/__init__.py b/python/__init__.py
index f4a8fac8..729e4f8a 100644
--- a/python/__init__.py
+++ b/python/__init__.py
@@ -21,6 +21,7 @@
import atexit
import sys
+from time import gmtime
# Binary Ninja components
import _binaryninjacore as core
@@ -147,6 +148,12 @@ core_version = core.BNGetVersionString()
core_build_id = core.BNGetBuildId()
'''Build ID'''
+core_serial = core.BNGetSerialNumber()
+'''Serial Number'''
+
+core_expires = gmtime(core.BNGetLicenseExpirationTime())
+'''License Expiration'''
+
core_product = core.BNGetProduct()
'''Product string from the license file'''
diff --git a/python/architecture.py b/python/architecture.py
index c4179b00..08049d46 100644
--- a/python/architecture.py
+++ b/python/architecture.py
@@ -111,6 +111,7 @@ class Architecture(object):
endianness = Endianness.LittleEndian
address_size = 8
default_int_size = 4
+ instr_alignment = 1
max_instr_length = 16
opcode_display_length = 8
regs = {}
@@ -133,6 +134,7 @@ class Architecture(object):
self.__dict__["endianness"] = Endianness(core.BNGetArchitectureEndianness(self.handle))
self.__dict__["address_size"] = core.BNGetArchitectureAddressSize(self.handle)
self.__dict__["default_int_size"] = core.BNGetArchitectureDefaultIntegerSize(self.handle)
+ self.__dict__["instr_alignment"] = core.BNGetArchitectureInstructionAlignment(self.handle)
self.__dict__["max_instr_length"] = core.BNGetArchitectureMaxInstructionLength(self.handle)
self.__dict__["opcode_display_length"] = core.BNGetArchitectureOpcodeDisplayLength(self.handle)
self.__dict__["stack_pointer"] = core.BNGetArchitectureRegisterName(self.handle,
@@ -245,6 +247,7 @@ class Architecture(object):
self._cb.getEndianness = self._cb.getEndianness.__class__(self._get_endianness)
self._cb.getAddressSize = self._cb.getAddressSize.__class__(self._get_address_size)
self._cb.getDefaultIntegerSize = self._cb.getDefaultIntegerSize.__class__(self._get_default_integer_size)
+ self._cb.getInstructionAlignment = self._cb.getInstructionAlignment.__class__(self._get_instruction_alignment)
self._cb.getMaxInstructionLength = self._cb.getMaxInstructionLength.__class__(self._get_max_instruction_length)
self._cb.getOpcodeDisplayLength = self._cb.getOpcodeDisplayLength.__class__(self._get_opcode_display_length)
self._cb.getAssociatedArchitectureByAddress = \
@@ -429,7 +432,8 @@ 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") or
+ (name == "get_instruction_alignment")):
raise AttributeError("attribute '%s' is read only" % name)
else:
try:
@@ -464,6 +468,13 @@ class Architecture(object):
log.log_error(traceback.format_exc())
return 4
+ def _get_instruction_alignment(self, ctxt):
+ try:
+ return self.__class__.instr_alignment
+ except:
+ log.log_error(traceback.format_exc())
+ return 1
+
def _get_max_instruction_length(self, ctxt):
try:
return self.__class__.max_instr_length
@@ -495,6 +506,7 @@ class Architecture(object):
if info is None:
return False
result[0].length = info.length
+ result[0].archTransitionByTargetAddr = info.arch_transition_by_target_addr
result[0].branchDelay = info.branch_delay
result[0].branchCount = len(info.branches)
for i in xrange(0, len(info.branches)):
@@ -1247,6 +1259,7 @@ class Architecture(object):
return None
result = function.InstructionInfo()
result.length = info.length
+ result.arch_transition_by_target_addr = info.archTransitionByTargetAddr
result.branch_delay = info.branchDelay
for i in xrange(0, info.branchCount):
target = info.branchTarget[i]
diff --git a/python/basicblock.py b/python/basicblock.py
index 26db925d..8e64c1c1 100644
--- a/python/basicblock.py
+++ b/python/basicblock.py
@@ -35,6 +35,14 @@ class BasicBlockEdge(object):
self.target = target
self.back_edge = back_edge
+ def __eq__(self, value):
+ if not isinstance(value, BasicBlockEdge):
+ return False
+ return (self.type, self.source, self.target, self.back_edge) == (value.type, value.source, value.target, value.back_edge)
+
+ def __hash__(self):
+ return hash((self.type, self.source, self.target, self.back_edge))
+
def __repr__(self):
if self.type == BranchType.UnresolvedBranch:
return "<%s>" % BranchType(self.type).name
@@ -68,6 +76,9 @@ class BasicBlock(object):
"""Internal method used to instantiante child instances"""
return BasicBlock(view, handle)
+ def __hash__(self):
+ return hash((self.start, self.end, self.arch.name))
+
@property
def function(self):
"""Basic block function (read-only)"""
diff --git a/python/binaryview.py b/python/binaryview.py
index 9304d412..6eb59db1 100644
--- a/python/binaryview.py
+++ b/python/binaryview.py
@@ -103,6 +103,17 @@ class StringReference(object):
class AnalysisCompletionEvent(object):
+ """
+ The ``AnalysisCompletionEvent`` object provides an asynchronous mechanism for receiving
+ callbacks when analysis is complete.
+
+ :Example:
+ >>> def on_complete(self):
+ ... print "Analysis Complete", self.view
+ ...
+ >>> evt = AnalysisCompletionEvent(bv, on_complete)
+ >>>
+ """
def __init__(self, view, callback):
self.view = view
self.callback = callback
@@ -114,7 +125,7 @@ class AnalysisCompletionEvent(object):
def _notify(self, ctxt):
try:
- self.callback()
+ self.callback(self)
except:
log.log_error(traceback.format_exc())
@@ -405,12 +416,13 @@ class BinaryViewType(object):
class Segment(object):
- def __init__(self, start, length, data_offset, data_length, flags):
+ def __init__(self, start, length, data_offset, data_length, flags, auto_defined):
self.start = start
self.length = length
self.data_offset = data_offset
self.data_length = data_length
self.flags = flags
+ self.auto_defined = auto_defined
@property
def executable(self):
@@ -439,7 +451,7 @@ class Segment(object):
class Section(object):
- def __init__(self, name, section_type, start, length, linked_section, info_section, info_data, align, entry_size, semantics):
+ def __init__(self, name, section_type, start, length, linked_section, info_section, info_data, align, entry_size, semantics, auto_defined):
self.name = name
self.type = section_type
self.start = start
@@ -450,6 +462,7 @@ class Section(object):
self.align = align
self.entry_size = entry_size
self.semantics = SectionSemantics(semantics)
+ self.auto_defined = auto_defined
@property
def end(self):
@@ -572,6 +585,7 @@ class BinaryView(object):
self._cb.getEntryPoint = self._cb.getEntryPoint.__class__(self._get_entry_point)
self._cb.isExecutable = self._cb.isExecutable.__class__(self._is_executable)
self._cb.getDefaultEndianness = self._cb.getDefaultEndianness.__class__(self._get_default_endianness)
+ self._cb.isRelocatable = self._cb.isRelocatable.__class__(self._is_relocatable)
self._cb.getAddressSize = self._cb.getAddressSize.__class__(self._get_address_size)
self._cb.save = self._cb.save.__class__(self._save)
self.file = file_metadata
@@ -828,6 +842,11 @@ class BinaryView(object):
return Endianness(core.BNGetDefaultEndianness(self.handle))
@property
+ def relocatable(self):
+ """Boolean - is the binary relocatable (read-only)"""
+ return core.BNIsRelocatable(self.handle)
+
+ @property
def address_size(self):
"""Address size of the binary (read-only)"""
return core.BNGetViewAddressSize(self.handle)
@@ -948,7 +967,7 @@ class BinaryView(object):
result = []
for i in xrange(0, count.value):
result.append(Segment(segment_list[i].start, segment_list[i].length,
- segment_list[i].dataOffset, segment_list[i].dataLength, segment_list[i].flags))
+ segment_list[i].dataOffset, segment_list[i].dataLength, segment_list[i].flags, segment_list[i].autoDefined))
core.BNFreeSegmentList(segment_list)
return result
@@ -962,7 +981,7 @@ class BinaryView(object):
result[section_list[i].name] = Section(section_list[i].name, section_list[i].type, section_list[i].start,
section_list[i].length, section_list[i].linkedSection, section_list[i].infoSection,
section_list[i].infoData, section_list[i].align, section_list[i].entrySize,
- section_list[i].semantics)
+ section_list[i].semantics, section_list[i].autoDefined)
core.BNFreeSectionList(section_list, count.value)
return result
@@ -1191,6 +1210,13 @@ class BinaryView(object):
log.log_error(traceback.format_exc())
return Endianness.LittleEndian
+ def _is_relocatable(self, ctxt):
+ try:
+ return self.perform_is_relocatable()
+ except:
+ log.log_error(traceback.format_exc())
+ return False
+
def _get_address_size(self, ctxt):
try:
return self.perform_get_address_size()
@@ -1483,6 +1509,19 @@ class BinaryView(object):
"""
return Endianness.LittleEndian
+ def perform_is_relocatable(self):
+ """
+ ``perform_is_relocatable`` implements a check which returns true if the BinaryView is relocatable. Defaults to
+ True.
+
+ .. note:: This method **may** be implemented for custom BinaryViews that are relocatable.
+ .. warning:: This method **must not** be called directly.
+
+ :return: True if the BinaryView is relocatable, False otherwise
+ :rtype: boolean
+ """
+ return True
+
def create_database(self, filename, progress_func=None):
"""
``create_database`` writes the current database (.bndb) file out to the specified file.
@@ -3316,7 +3355,7 @@ class BinaryView(object):
if not core.BNGetSegmentAt(self.handle, addr, segment):
return None
result = Segment(segment.start, segment.length, segment.dataOffset, segment.dataLength,
- segment.flags)
+ segment.flags, segment.autoDefined)
return result
def get_address_for_data_offset(self, offset):
@@ -3349,7 +3388,7 @@ class BinaryView(object):
result.append(Section(section_list[i].name, section_list[i].type, section_list[i].start,
section_list[i].length, section_list[i].linkedSection, section_list[i].infoSection,
section_list[i].infoData, section_list[i].align, section_list[i].entrySize,
- section_list[i].semantics))
+ section_list[i].semantics, section_list[i].autoDefined))
core.BNFreeSectionList(section_list, count.value)
return result
@@ -3358,7 +3397,8 @@ class BinaryView(object):
if not core.BNGetSectionByName(self.handle, name, section):
return None
result = Section(section.name, section.type, section.start, section.length, section.linkedSection,
- section.infoSection, section.infoData, section.align, section.entrySize, section.semantics)
+ section.infoSection, section.infoData, section.align, section.entrySize, section.semantics,
+ section_list.autoDefined)
core.BNFreeSection(section)
return result
diff --git a/python/examples/nes.py b/python/examples/nes.py
index e55a90b7..39544c9f 100644
--- a/python/examples/nes.py
+++ b/python/examples/nes.py
@@ -367,6 +367,7 @@ class M6502(Architecture):
name = "6502"
address_size = 2
default_int_size = 1
+ instr_alignment = 1
max_instr_length = 3
regs = {
"a": RegisterInfo("a", 1),
diff --git a/python/function.py b/python/function.py
index db4ca0f5..10583b58 100644
--- a/python/function.py
+++ b/python/function.py
@@ -171,6 +171,8 @@ class PossibleValueSet(object):
self.reg = arch.get_reg_name(value.value)
elif value.state == RegisterValueType.ConstantValue:
self.value = value.value
+ elif value.state == RegisterValueType.ConstantPointerValue:
+ self.value = value.value
elif value.state == RegisterValueType.StackFrameOffset:
self.offset = value.value
elif value.state == RegisterValueType.SignedRangeValue:
@@ -212,6 +214,8 @@ class PossibleValueSet(object):
return "<entry %s>" % self.reg
if self.type == RegisterValueType.ConstantValue:
return "<const %#x>" % self.value
+ if self.type == RegisterValueType.ConstantPointerValue:
+ return "<const ptr %#x>" % self.value
if self.type == RegisterValueType.StackFrameOffset:
return "<stack frame offset %#x>" % self.offset
if self.type == RegisterValueType.SignedRangeValue:
@@ -290,10 +294,10 @@ class Variable(object):
return self.name
def __eq__(self, other):
- return self.identifier == other.identifier
+ return (self.identifier, self.function) == (other.identifier, other.function)
def __hash__(self):
- return hash(self.identifier)
+ return hash((self.identifier, self.function))
class ConstantReference(object):
@@ -356,6 +360,8 @@ class Function(object):
self._view = view
self.handle = core.handle_of_type(handle, core.BNFunction)
self._advanced_analysis_requests = 0
+ self._arch = None
+ self._platform = None
def __del__(self):
if self._advanced_analysis_requests > 0:
@@ -407,18 +413,26 @@ class Function(object):
@property
def arch(self):
"""Function architecture (read-only)"""
- arch = core.BNGetFunctionArchitecture(self.handle)
- if arch is None:
- return None
- return architecture.Architecture(arch)
+ if self._arch:
+ return self._arch
+ else:
+ arch = core.BNGetFunctionArchitecture(self.handle)
+ if arch is None:
+ return None
+ self._arch = architecture.Architecture(arch)
+ return self._arch
@property
def platform(self):
"""Function platform (read-only)"""
- plat = core.BNGetFunctionPlatform(self.handle)
- if plat is None:
- return None
- return platform.Platform(None, handle = plat)
+ if self._platform:
+ return self._platform
+ else:
+ plat = core.BNGetFunctionPlatform(self.handle)
+ if plat is None:
+ return None
+ self._platform = platform.Platform(None, handle = plat)
+ return self._platform
@property
def start(self):
@@ -768,6 +782,41 @@ class Function(object):
"""Sets a comment for the current function"""
return core.BNSetFunctionComment(self.handle, comment)
+ @property
+ def llil_basic_blocks(self):
+ """A generator of all LowLevelILBasicBlock objects in the current function"""
+ for block in self.low_level_il:
+ yield block
+
+ @property
+ def mlil_basic_blocks(self):
+ """A generator of all MediumLevelILBasicBlock objects in the current function"""
+ for block in self.medium_level_il:
+ yield block
+
+ @property
+ def instructions(self):
+ """A generator of instruction tokens and their start addresses for the current function"""
+ for block in self.basic_blocks:
+ start = block.start
+ for i in block:
+ yield (i[0], start)
+ start += i[1]
+
+ @property
+ def llil_instructions(self):
+ """A generator of llil instructions of the current function"""
+ for block in self.llil_basic_blocks:
+ for i in block:
+ yield i
+
+ @property
+ def mlil_instructions(self):
+ """A generator of mlil instructions of the current function"""
+ for block in self.mlil_basic_blocks:
+ for i in block:
+ yield i
+
def __iter__(self):
count = ctypes.c_ulonglong()
blocks = core.BNGetFunctionBasicBlockList(self.handle, count)
@@ -829,7 +878,13 @@ class Function(object):
"""
if arch is None:
arch = self.arch
- return self.low_level_il[core.BNGetLowLevelILForInstruction(self.handle, arch.handle, addr)]
+
+ idx = core.BNGetLowLevelILForInstruction(self.handle, arch.handle, addr)
+
+ if idx == len(self.low_level_il):
+ return None
+
+ return self.low_level_il[idx]
def get_low_level_il_exits_at(self, addr, arch=None):
if arch is None:
@@ -980,7 +1035,13 @@ class Function(object):
def get_lifted_il_at(self, addr, arch=None):
if arch is None:
arch = self.arch
- return self.lifted_il[core.BNGetLiftedILForInstruction(self.handle, arch.handle, addr)]
+
+ idx = core.BNGetLiftedILForInstruction(self.handle, arch.handle, addr)
+
+ if idx == len(self.lifted_il):
+ return None
+
+ return self.lifted_il[idx]
def get_lifted_il_flag_uses_for_definition(self, i, flag):
flag = self.arch.get_flag_index(flag)
@@ -1833,6 +1894,7 @@ class InstructionBranch(object):
class InstructionInfo(object):
def __init__(self):
self.length = 0
+ self.arch_transition_by_target_addr = False
self.branch_delay = False
self.branches = []
diff --git a/python/functionrecognizer.py b/python/functionrecognizer.py
index 8514a2ee..4ac304ca 100644
--- a/python/functionrecognizer.py
+++ b/python/functionrecognizer.py
@@ -36,6 +36,7 @@ class FunctionRecognizer(object):
self._cb = core.BNFunctionRecognizer()
self._cb.context = 0
self._cb.recognizeLowLevelIL = self._cb.recognizeLowLevelIL.__class__(self._recognize_low_level_il)
+ self._cb.recognizeMediumLevelIL = self._cb.recognizeMediumLevelIL.__class__(self._recognize_medium_level_il)
@classmethod
def register_global(cls):
@@ -62,3 +63,17 @@ class FunctionRecognizer(object):
def recognize_low_level_il(self, data, func, il):
return False
+
+ def _recognize_medium_level_il(self, ctxt, data, func, il):
+ try:
+ file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(data))
+ view = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(data))
+ func = function.Function(view, handle = core.BNNewFunctionReference(func))
+ il = mediumlevelil.MediumLevelILFunction(func.arch, handle = core.BNNewMediumLevelILFunctionReference(il))
+ return self.recognize_medium_level_il(view, func, il)
+ except:
+ log.log_error(traceback.format_exc())
+ return False
+
+ def recognize_medium_level_il(self, data, func, il):
+ return False
diff --git a/python/interaction.py b/python/interaction.py
index 979549f5..96cac42d 100644
--- a/python/interaction.py
+++ b/python/interaction.py
@@ -520,7 +520,7 @@ def show_html_report(title, contents, plaintext=""):
:param str contents: HTML contents to display
:param str plaintext: Plain text version to display (used on the command line)
:rtype: None
- :Example"
+ :Example:
>>> show_html_report("title", "<h1>Contents</h1>", "Plain text contents")
Plain text contents
"""
diff --git a/python/lowlevelil.py b/python/lowlevelil.py
index 3810e742..42c34ee0 100644
--- a/python/lowlevelil.py
+++ b/python/lowlevelil.py
@@ -2171,6 +2171,9 @@ class LowLevelILBasicBlock(basicblock.BasicBlock):
"""Internal method by super to instantiante child instances"""
return LowLevelILBasicBlock(view, handle, self.il_function)
+ def __hash__(self):
+ return hash((self.start, self.end, self.il_function))
+
def LLIL_TEMP(n):
return n | 0x80000000
diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py
index 144c7e0b..85feba0a 100644
--- a/python/mediumlevelil.py
+++ b/python/mediumlevelil.py
@@ -40,12 +40,12 @@ class SSAVariable(object):
def __eq__(self, other):
return (
- (self.var.identifier, self.version) ==
- (other.var.identifier, other.version)
+ (self.var, self.version) ==
+ (other.var, other.version)
)
def __hash__(self):
- return hash((self.var.identifier, self.version))
+ return hash((self.var, self.version))
class MediumLevelILLabel(object):
@@ -921,3 +921,6 @@ class MediumLevelILBasicBlock(basicblock.BasicBlock):
def _create_instance(self, view, handle):
"""Internal method by super to instantiante child instances"""
return MediumLevelILBasicBlock(view, handle, self.il_function)
+
+ def __hash__(self):
+ return hash((self.start, self.end, self.il_function))
diff --git a/python/pluginmanager.py b/python/pluginmanager.py
index 6896d699..2f293577 100644
--- a/python/pluginmanager.py
+++ b/python/pluginmanager.py
@@ -382,7 +382,6 @@ class RepositoryManager(object):
>>> mgr = RepositoryManager()
>>> mgr.add_repository(url="https://github.com/vector35/community-plugins.git",
repopath="myrepo",
- repomanifest="plugins",
localreference="master", remotereference="origin")
True
>>>
diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py
index ed9688b9..c92c249a 100644
--- a/python/scriptingprovider.py
+++ b/python/scriptingprovider.py
@@ -42,14 +42,14 @@ class _ThreadActionContext(object):
def __init__(self, func):
self.func = func
self.interpreter = None
- if "value" in dir(PythonScriptingInstance._interpreter):
+ if hasattr(PythonScriptingInstance._interpreter, "value"):
self.interpreter = PythonScriptingInstance._interpreter.value
self.__class__._actions.append(self)
self.callback = ctypes.CFUNCTYPE(None, ctypes.c_void_p)(lambda ctxt: self.execute())
def execute(self):
old_interpreter = None
- if "value" in dir(PythonScriptingInstance._interpreter):
+ if hasattr(PythonScriptingInstance._interpreter, "value"):
old_interpreter = PythonScriptingInstance._interpreter.value
PythonScriptingInstance._interpreter.value = self.interpreter
try:
@@ -380,7 +380,7 @@ class _PythonScriptingInstanceOutput(object):
def write(self, data):
interpreter = None
- if "value" in dir(PythonScriptingInstance._interpreter):
+ if hasattr(PythonScriptingInstance._interpreter, "value"):
interpreter = PythonScriptingInstance._interpreter.value
if interpreter is None:
@@ -419,7 +419,7 @@ class _PythonScriptingInstanceInput(object):
def read(self, size):
interpreter = None
- if "value" in dir(PythonScriptingInstance._interpreter):
+ if hasattr(PythonScriptingInstance._interpreter, "value"):
interpreter = PythonScriptingInstance._interpreter.value
if interpreter is None:
@@ -434,7 +434,7 @@ class _PythonScriptingInstanceInput(object):
def readline(self):
interpreter = None
- if "value" in dir(PythonScriptingInstance._interpreter):
+ if hasattr(PythonScriptingInstance._interpreter, "value"):
interpreter = PythonScriptingInstance._interpreter.value
if interpreter is None:
@@ -457,7 +457,7 @@ class PythonScriptingInstance(ScriptingInstance):
super(PythonScriptingInstance.InterpreterThread, self).__init__()
self.instance = instance
self.locals = {"__name__": "__console__", "__doc__": None, "binaryninja": sys.modules[__name__]}
- self.interpreter = code.InteractiveInterpreter(self.locals)
+ self.interpreter = code.InteractiveConsole(self.locals)
self.event = threading.Event()
self.daemon = True
@@ -484,7 +484,7 @@ class PythonScriptingInstance(ScriptingInstance):
self.code = None
self.input = ""
- self.interpreter.runsource("from binaryninja import *\n")
+ self.interpreter.push("from binaryninja import *\n")
def execute(self, code):
self.code = code
@@ -540,8 +540,15 @@ class PythonScriptingInstance(ScriptingInstance):
self.locals["current_address"] = self.active_addr
self.locals["here"] = self.active_addr
self.locals["current_selection"] = (self.active_selection_begin, self.active_selection_end)
+ if self.active_func == None:
+ self.locals["current_llil"] = None
+ self.locals["current_mlil"] = None
+ else:
+ self.locals["current_llil"] = self.active_func.low_level_il
+ self.locals["current_mlil"] = self.active_func.medium_level_il
- self.interpreter.runsource(code)
+ for line in code.split("\n"):
+ self.interpreter.push(line)
if self.locals["here"] != self.active_addr:
if not self.active_view.file.navigate(self.active_view.file.view, self.locals["here"]):
diff --git a/python/update.py b/python/update.py
index be6962d7..1eb8ea61 100644
--- a/python/update.py
+++ b/python/update.py
@@ -154,7 +154,7 @@ class UpdateChannel(object):
def updates_available(self):
"""Whether updates are available (read-only)"""
errors = ctypes.c_char_p()
- result = core.BNAreUpdatesAvailable(self.name, errors)
+ result = core.BNAreUpdatesAvailable(self.name, None, None, errors)
if errors:
error_str = errors.value
core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte)))